CActiveRecord Events Problems

I have class


class Banlist extends CActiveRecord

{

    public static function model($className=__CLASS__)

    {

        return parent::model($className);

    }

   

    // this method doesn't call

    public function onAfterSave($event) {        

      // log activity logic

    }

}



CActiveRecord has method ( which is being succesfully called ):




protected function afterSave()

{

	if($this->hasEventHandler('onAfterSave'))

		$this->onAfterSave(new CEvent($this));

}



But $this->hasEventHandler(‘onAfterSave’) always returns false




CComponent

/**

* Checks whether the named event has attached handlers.

* @param string the event name

* @return boolean whether an event has been attached one or several handlers

*/

public function hasEventHandler($name)

{

	$name=strtolower($name);

	return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0;

}



because $this->_e doesn’t contain [$name]

Please help me to make this feature usable

  1. Change the method signature to



protected function onAfterSave($event) {        



  1. See attachEventHandler

http://www.yiiframework.com/doc/api/CComponent#attachEventHandler-detail

/Tommy

  1. My bad, I erroneously read afterSave() instead of onAfterSave()

(You can override afterSave in an inherited class)

  1. (IIRC) The framework will raise the event in the function onAfterSave(), which also serves the purpose of declaring the event name. You will have to attach a handler method that would get called by the event.

/Tommy

  1. Page displays nothing (error)

  2. Why I have to use attachEventHandler, if this is existed public method

http://www.yiiframework.com/doc/api/CActiveRecord#onAfterSave-detail

Thank you!

That’s because you’re not registering an event handler. onAfterSave() is never called. You could register your method, but an easier way is to override the afterSave() method:




protected function afterSave() {

  parent::afterSave();

  ... // Do your own stuff

}



Don’t get confused with these different methods. Their purpose is like this:

onAfterSave:

If a method with ‘on…’ exists in a component, Yii detects this as an available event for that component. That means, you can attach handlers to that event. The implementation of this method can contain any code. In the default implementation it simply fires the event with the same name.

afterSave:

This method is called automatically by AR. You can override this method in your AR class. That’s convenient as you don’t have to attach any handler. The default implementation in CActiveRecord will simply check if any event handlers where attached to that event and fire the event by calling onAfterSave().

Seems like my reply got lost by the forum software (or my ISP is to blame).

(Also Sander beat me to it)

  1. I erroneously read afterSave() instead of onAfterSave(). As said you can choose to override afterSave() in an inherited class.

  2. IIRC the framework will raise the event inside the method onAfterSave(), which also serves the purpose of declaring the event. As said you will have to attach a handler method.

/Tommy

Here what I found in Yii

How do I can attach this class to CActiveRecord?

I thought framework should do that automatically ( http://www.yiiframework.com/doc/api/CActiveRecord#events ). Could it be a bug?

btw methods (onBeforeValidate, onAfterValidate) work as I want (like in my first post). Seems because of they defined in CModel.




/**

 * CActiveRecordBehavior is the base class for behaviors that can be attached to {@link CActiveRecord}.

 * Compared with {@link CModelBehavior}, CActiveRecordBehavior attaches to more events

 * that are only defined by {@link CActiveRecord}.

 *

 * @author Qiang Xue <qiang.xue@gmail.com>

 * @version $Id: CActiveRecordBehavior.php 1678 2010-01-07 21:02:00Z qiang.xue $

 * @package system.db.ar

 * @since 1.0.2

 */

class CActiveRecordBehavior extends CModelBehavior

{

	/**

	 * Declares events and the corresponding event handler methods.

	 * If you override this method, make sure you merge the parent result to the return value.

	 * @return array events (array keys) and the corresponding event handler methods (array values).

	 * @see CBehavior::events

	 */

	public function events()

	{

		return array_merge(parent::events(), array(

			'onBeforeSave'=>'beforeSave',

			'onAfterSave'=>'afterSave',

			'onBeforeDelete'=>'beforeDelete',

			'onAfterDelete'=>'afterDelete',

			'onAfterConstruct'=>'afterConstruct',

			'onBeforeFind'=>'beforeFind',

			'onAfterFind'=>'afterFind',

		));

	}



I suggest you read more about this in the guide:

http://www.yiiframework.com/doc/guide/basics.component, Subsections Component Event and Component Behaviors.

http://www.yiiframework.com/doc/guide/extension.use, Subsection Behavior.

In regard to your post:

The CActiveRecordBehavior class, when instantiated and attached actually attaches a set of event handlers named beforeSave, afterSave, beforeDelete, …

The attach method is located in the base class CBehavior.php:




public function attach($owner)

{

  $this->_owner=$owner;

  foreach($this->events() as $event=>$handler)

    $owner->attachEventHandler($event,array($this,$handler));

}



API documentation: http://www.yiiframework.com/doc/api/CComponent#attachEventHandler-detail

/Tommy