When using CakePHP's (v2.x) saveAll
method on a model you may have found that the afterSave
callback for the model isn't being called after everything has saved. Instead it is called just after the primary model is saved and before saving the associated model data. This can be a bit of a problem if you want to play around with the data from the associated models being saved in the saveAll
. The way to get around this is to extend the saveAll
method and create a new callback, afterSaveAll
.
If you want this functionality across your app then you'll want to extend saveAll
in your AppModel
, otherwise it might make more sense to keep the extended code to the model you want to add the callback to to prevent slowdown incurred by the additional callback check.
We need to add an afterSaveAll
event to the model's lifecycle:-
/**
* Returns a list of all events that will fire in the model
* during it's lifecycle.
*
* @return array
*/
public function implementedEvents() {
$events = parent::implementedEvents();
$events['Model.afterSaveAll'] = array(
'callable' => 'afterSaveAll',
'passParams' => true
);
return $events;
}
Next we extend the Model::saveAll
method:-
public function saveAll($data = array(), $options = array()) {
$defaults = array(
'callbacks' => true
);
$options = array_merge($defaults, $options);
$success = parent::saveAll($data, $options);
if ($success && ($options['callbacks'] === true || $options['callbacks'] === 'afterAll')) {
$event = new CakeEvent('Model.afterSaveAll',
$this, array($options));
$this->getEventManager()->dispatch($event);
}
return $success;
}
This will fire the afterSaveAll
event after all the saves are successfully completed by saveAll
unless we've disabled callbacks.
Finally we need to define the callback itself:-
public function afterSaveAll($options = array()) {
return;
}
With this in place you should now be able to use the afterSaveAll
callback whenever you use saveAll
.