Blake Miller Tue Mar 20 14:19:43 -0400 2012

Subject: Calling save() in after_create, results in recursive saves

I'm using an after_create callback to update a confirmation number.

static $after_create = array('set_confirmation_nbr');
function set_confirmation_nbr() {
$this->confirmationnumber = str_replace("/", "", date( 'm/d/Y', $this->datecreated ))."-".$this->id;
$this->save();
}

This code will recursively save loads of records to the database. If I take out the $this-save(), I get one record, but naturally the confirmation number isn't saved. Is it not recommended to alter the existing model in an after callback?


Blake Miller Tue Mar 20 18:40:09 -0400 2012

The workaround I've found is:

static $after_create = array('set_confirmation_nbr');
function set_confirmation_nbr() {
$ef = EnrollmentForm::find($this->id);
$ef->confirmationnumber = str_replace("/", "", date("m/d/Y", strtotime($ef->datecreated)))."-".$ef->id;
$ef->save();
}

Basically I'm looking up the record again from the database, altering it, and resaving it. Something is fishy about $this in the after_create callback.

Megan McVey Sat Apr 06 03:14:36 -0400 2013

Haven't checked if this is fixed in the live branch, but the version I have has

$this->invoke_callback('after_create',false);
$this->__new_record = false;

in Model.php (ll.827-828)

So during the callback the new record is still marked as __new_record==true
Thus if you call save in the callback on "this" it tries to do an insert.
Since it has cleared the dirty flag on all the existing fields it would try to insert a new record using only the newly dirty attributes - your confirmation. Since there is nothing causing it to fail (validations), it succeeds and recalls the callback ad infinitum (if it fails on a validation or a database integrity check it would die there).

A simple flip of those two lines fix the problem - but I don't know the internals of phpAR well enough to know if it would break something else.

It fixes it in my system, but ... YMMV.

anther's github (https://github.com/anther/php-activerecord/tree/after_create_fix) has the switch lines fix.

(1-2/2)