phpeventscakephpbehaviordispatchevent

CakePHP: Triggering Custom Event in Behaviour


Because of how my application is built, I need to create event handlers for beforeSaveAssociated and afterSaveAssociated. To allow for this, I've updated AppModel.php to contain the following relevant code:

public function saveAssociated(array $data = null, array $options = array()) {
    $this->after_save_options = NULL;

    $event = new CakeEvent('Model.beforeSaveAssociated', $this, array(&$data, &$options));
    $this->after_save_options = NULL;
    $this->getEventManager()->dispatch($event);

    if (parent::saveAssociated($data, $options)) {
        if (is_array($this->after_save_options)) {
            $curData = $this->data;
            $this->data = $this->_tempData;
            $event = new CakeEvent('Model.afterSaveAssociated', $this, $this->after_save_options);
            $this->after_save_options = NULL;
            $this->getEventManager()->dispatch($event);
            $this->data = $curData;
        }
        if ($this->_tempData) {
            $this->_tempData = FALSE;
        }
        return TRUE;
    }
    return FALSE;
}

public function implementedEvents() {
    return array_merge(parent::implementedEvents(), array(
        'Model.beforeSaveAssociated' => array(
            'callable' => 'beforeSaveAssociated',
            'passParams' => TRUE,
        ),
        'Model.afterSaveAssociated' => array(
            'callable' => 'afterSaveAssociated',
            'passParams' => TRUE,
        ),
    ));
}

Although this works fine for any beforeSaveAssociated defined within a model class, whenever I define it in a behaviour, it doesn't get triggered. If I update saveAssociated above to trigger Model.beforeSave (a built-in event), it does work, so as far as I can tell, it's not an issue with the behaviour not being properly attached.

Any help is greatly appreciated,


Solution

  • I think this is because the BehaviorCollection is just listening to these events (taken from the class):

    public function implementedEvents() {
        return array(
            'Model.beforeFind' => 'trigger',
            'Model.afterFind' => 'trigger',
            'Model.beforeValidate' => 'trigger',
            'Model.afterValidate' => 'trigger',
            'Model.beforeSave' => 'trigger',
            'Model.afterSave' => 'trigger',
            'Model.beforeDelete' => 'trigger',
            'Model.afterDelete' => 'trigger'
        );
    }
    

    Not the behaviors listen to the events but the collection and triggers them on behaviors. Not 100% sure about that without looking it up but I think that's how it works.

    What you could try to do is to make the behavior that needs to receive these events directly to listen the event.