I’m gonna put a note in here, in case I ever forget how this stuff works.
First:
SomeClass, from the example above, can be replaced with any valid PHP callback, meaning a global function, method of a class or an anonymous function:
'handleOnClick' // handleOnClick() is a global function
array($object,'handleOnClick') // using $object->handleOnClick()
array('Page','handleOnClick') // using Page::handleOnClick()
$component->onClicked=function($event) {
......
}
Just be aware of the scopes!
Second:
Be aware, that event handeling is not magic. You don’t just raise the event and the function gets executed miraculously. For an existing object extending CComponent you can define an event. This is done by so:
public function onSomethingGoesOn($event)
{
$this->raiseEvent('onSomethingGoesOn', $event);
}
Notice the $this->raiseEvent() call inside. This is placed here, so that calling $obj->onSomethingGoesOn($event) raises the event. This is independent of what you attached to the event (aside from it’s name and existance)! You can raise the event direcly, you don’t have to have anything inside the function, but with that you lose your shortcut, and possible pre/post process for the event. Also note the scope of the function - it is called through $obj, so the $this call in the function refers to $obj itself - this is important in part three.
Three:
As mentioned before the onSomethingGoesOn function doesn’t gets called if you raise the event directly, the method exists so that you can have event handlers attached to it. When you equal an event handler to a function whose name begins with ‘on’, Yii recognises that it should be an event (through the CComponent class implementation of the __set() magic function of PHP) and stores the callback in an array (this is how the events can be ordered) with the function’s name as the array key (onSomethingGoesOn in this case). When the event is raised the callbacks in the array are executed in order, after the $event->handled flag is checked.
Four (AKA where the event is attached):
The only thing to note here is to attach the event handler before you raise the event. In practice the controller, handeling the object that raises the event, is a good place to attach handlers:
class Button extends CComponent
{
public $id;
public function click()
{
//some process of the click, maybe an onBeforeClick event raised
$this->onClick();
//some process, maybe an onAfterClick event raised
}
public function onClick()
{
$this->raiseEvent('onClick',new CEvent($this)); //this is where the event starts, hence there is no $event variable passed
}
}
class ClickHandler
{
public function buttonClick($event)
{
$btn=$event->sender;
//do something about the clicking
}
}
class ButtonController extends BaseClickController
{
public function actionClick()
{
$id=Yii::app()->request->getQuery('id',NULL);
if($id===NULL)
throw new CHttpExeption(404,'Nonexistent page!');
$button=new Button;
$button->id=$id;
$button->onClick= array(new ClickHandler, 'buttonClick'); // attaching the handler here
$button->click();
}
}
One can have an application componet to handle all events as well. So instead of calling $button->click, you can call Yii::app()->events->click($button). The ‘events’ component’s init function, or the click function itself attaches the different handlers, and raises the button’s click event (it could be enough to pass $id, as long as the rest is inside the application component).
Hope I’m correct on this, and that it is usefull for others as well.