Events And Yii

Hi,

i’m currently doing a research on events in Yii to find out how it is working and what is possible.

I have 2 questions:

At first: Is it possible to return a result from an eventhandler?

When i add a eventhandler to an event like in the example below, will the return from ‘eventHandler1’ saved in

$myComponent->onForestRan? If not is there a possiblity to get the return value from a handler?


$myComponent->onForestRan = array(new SomeOtherClass, 'eventHandler1');

Second question: Is it possible to build an eventchain(an event calls another event and so on…)? Additional to this question is it possible to return values through the chain?

Sorry for my bad english. I hope you understand my questions.

Thanks a lot!

Hi jbru,

first of all: I don’t think events should be used to collect stuff. An application should not decide what to next depending of results of event handlers. Events happen. If an event is being raised, it indicates that something just had happened. It’s a mechanism for other components to be notified and take according actions on their own behalf. Not for other components to feedback information about how to go on. But that’s maybe only my very own point of view regarding events. Throughout the framework, there are a few uses of events that do exactly what I think they should not do. For example CActiveRecord’s onBeforeSave event can be used cancel a save operation.

To make something like this work you need to pass something to the event handlers when you invoke the event. The event handlers can work on this data, to indicate what they normally would return. It’s not possible to simply return some value from your event handler, because there might be many event handlers attached to one event (well I guess it would be possible to store all the results in a list, but the framework does not do anything like that):




$myComponent->onForestRan = array(new SomeOtherClass, 'eventHandler1');

$myComponent->onForestRan = array(new SomeOtherClass, 'eventHandler2');



So when the ForestRan event is raised, those two handlers will be invoked one after another. Remember how the event handler’s signature looks like:




public funtion SomeOtherClass::eventHandler1( CEvent $event )

{

}



You normally raise the event by doing something like this:




// definition of the event

public function onForestRan($event)

{

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

}


public function somewhereElse()

{

  // invocation of the event

  $event = new CEvent( $this /*, array('param1'=>$value1, 'param2'=>$value2) */);

  $this->onForestRun( $event );

}



Now to collect results from your event handlers, you can either use your own EventClass, or you can pass a reference to the handlers.

First example, using own class:




class ForestRanEvent extends CEvent

{

  public $aResults = array();

}


// definition of the event

public function onForestRan($event) {

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

}


public function somewhereElse()

{

  // invocation of the event

  $event = new ForestRanEvent( $this /*, array('param1'=>$value1, 'param2'=>$value2) */);

  $this->onForestRan( $event );


  // check results

  foreach ($event->aResults as $result) {

    // ...

  }

}


// handling the event and returning data

public funtion SomeOtherClass::eventHandler1( ForestRanEvent $event )

{

  // do stuff


  // "return" result

  $event->aResults[] = $thisHandlersResult;

}



Second example, using reference:




// definition of the event

public function onForestRan($event) {

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

}


public function somewhereElse()

{

  // invocation of the event

  $aResults = array();

  $event = new CEvent( $this, array(

    'results' => &$aResults,  // pass results array as reference

    /*

    'param1' => $value1,

    'param2' => $value2,

    */

  ));

  $this->onForestRan( $event );


  // check results

  foreach ($aResults as $result) {

    // ...

  }

}


// handling the event and returning data

public funtion SomeOtherClass::eventHandler1( CEvent $event )

{

  // do stuff


  // "return" result

  $event->params['results'][] = $thisHandlersResult;

}