Skip to content

CakePHP's Missing Model::afterSaveAll() Callback

2 min read

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));
	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()) {

With this in place you should now be able to use the afterSaveAll callback whenever you use saveAll.

© 2024 Andy Carter