Request for Component Event example

Hi, I’ve spent a couple of hours trying to understand the Component Event docs, but I can’t understand them at all. I’ve fiddled with some code, and while I can get some communication going between a test controller method and a component with an event handler, what I have is of no real world use.

Would it be possible for someone to post a simple component that implements an event handler and a snippet of code to test it, please.

Once I understand what’s happening here, I’ll rewrite the docs, so that they are a bit more comprehensible.

Thanks.




class SomeClass

{

  public function eventHandler($event)

  {

    ...

    $event->handled=true; // no further process gets done in the current event

  }

}


class YourComponent extends CComponent

{

  public function onSomethingGoesOn($event)

  {

    $this->raiseEvent('onSomethingGoesOn', $event);

  }

}



This is it in its simplest form. We have a component with a single event set up (onSomethingGoesOn).

You can attach event handlers to this event as follows:




$yourComponent=new YourComponent;

$yourComponent->onSomethingGoesOn = array(new SomeClass, 'eventHandler');



This way whenever you process this event (with calling


$this->onSomethingGoesOn(new CEvent($this))

in YourComponent), SomeClass::eventHandler will take control and handle the event as implemented.

If you still have questions, ask. :)

If you download my extension (psYiiExtensions) the CPSAPIComponent implements a few events (onBeforeAPICall, etc.) which will demonstrate all the necessary parts. Not that the post above is incorrect, just that it’s not a “live” example.

pestaa, thanks very much for taking the time to put something together. Much appreciated. I can see the point I was missing just scanning your code. I will keep asking questions until I understand anything. I know lots of stuff, but not everything.

xx666xx thanks too. I d/l’d your extension and will dig into it. Regardless, it looks like being very useful. Thanks.

This post has helped me to better understand the use of events and behaviours.

It will be nice if any of you (pestaa or lucifurious) write a good wiki about it; with some example scenarios. I think tutos are not quite clear about it for newbies to the framework.

Thanks to all

pestaa, thank you very much. Your post helped me to understand components.

pestaa my question is where to put this some class???????????where to start with…I am not clear about the accessibilty of the variables,properties and methods…Please help as I am very keen ti undersatnd this framework …I have read documentations and books also but not very clear about most of the things

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.