Yii 1.1: Behaviors & events

54 followers

These features provide endless possibilities and unbelievable flexibility, but as current documentation does not give more than a few examples, it might be difficult to fully understand their internals and requirements.

It should be noted that they do mostly the same thing. You can attach behaviors and event handlers to components to modify the components' behavior.

Events

It is useful when you want to interrupt the normal application flow without extending base classes.

For example, enabling gzip compression on the output could be done via extending CWebApplication. But because there are entry points for event handlers, one can do this:

Yii::app()->onBeginRequest = create_function('$event', 'return ob_start("ob_gzhandler");'),
Yii::app()->onEndRequest = create_function('$event', 'return ob_end_flush();'),

You can create an event handler -- which is simply a method in some class with a specific signature -- and attach it to the event of an object. You can add as many event handlers as you wish, from as many objects as you wish. If the event handler is, effectively static, then you can create the object as you assign it:

$test_comp->onSomethingGoesOn = array(new SomeClass, 'eventHandler1');
$test_comp->onSomethingGoesOn = array(new SomeOtherClass, 'eventHandler2');
$test_comp->onSomethingGoesOn = array(new YetAnotherClass, 'eventHandler3');

As long as you have a handle on the object, then you can add an event handler to it.

At some point, you can then raise the event with something like one of these:

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

So, basically, it allows you to build a list of function calls that can later be executed, in the order they were added. It can save you passing around a lot of object refs and building conditional code, since you can still raise the event, even if it doesn't do anything.

Behaviors

Behaviors are simply a way of adding methods to an object.

Take this scenario: You have 2 classes: MySuperClass1, MySuperClass2. There might be lots of methods from MySuperClass1 & 2 that you want in some new class, say MyBoringClass. Unfortunately, php does not allow for this:

class MyBoringClass extends MySuperClass1, MySuperClass2 {
}

This is where behaviors come in. Instead, you can go:

class MyBoringClass extends MySuperClass1 {
}
 
$classInstance = new MyBoringClass();
$classInstance->attachbehavior('uniqueName', new MySuperClass2);

Now $classInstance has all the methods from MySuperClass1 and MySuperClass2. Since MySuperClass2 is being used as a behavior, it has to extend CBehavior. The only caveat to this is an attached behavior cannot override any class methods of the component it is being attached to. If a method already exists, if it be from the original class or already added by a previously attached behavior, it will not be overwritten.

In an OO language like Ruby, it's quite possible to start with a completely empty object and simply build its behavior as you go along. Yii provides this behavior with a little magic. The key is that the class you wish to add the behavior from must extend Cbehavior.

class SomeClass extends CBehavior
{
    public function add($x, $y) { return $x + $y; }
}

Then use with:

$test_comp = new TestComponent(); 
$test_comp->attachbehavior('blah', new SomeClass);
$test_comp->add(2, 5);

So, in this case, you are extending the functionality of an object with functionality of another object.

After studying this cookbook page you are encouraged to reread the corresponding guide page as it contains advanced information (for example, if you are familiar with interfaces, you might find it enough to implement IBehavior before extending CBehavior).

Total 10 comments

#18168 report it
Ashish Mahana at 2014/09/19 02:14am
Confused!!!

where to write the code below i.e. to attach the event to a handler

$test_comp->onSomethingGoesOn = array(new SomeClass, 'eventHandler1');

#16249 report it
nashashmi at 2014/02/03 11:50am
Alternate tutorial

If anybody is confused by this tutorial but still wants to learn more about events, I will give you the following example presented as a single file. The example is taken from the forums.

The summary of this example: You initiate an action on your controller to get a typical web page. In the controller, you use a custom component class that was created (Data in this example) with methods to do whatever it was that needed to be done (add in this example). But you want to modify or extend the ability of the component to do other things without physically touching the file or making a copy of it, but by adding random functions while using the component in your code just for that one instance of use. You want the function to be executed at a certain moment in the component's operation, plus you want the function to have access to whatever variables are available at that moment.

So you create the controller with an action, use a component (Data), create/use a function that uses component's internal variables, and add the function to the component.

On the component side, you bookmark a place where you want the custom functions to be executed and make variables available to that bookmark.

class Data extends CComponent // our component is Data
{
  public $id;
  public function add($var1) 
  {
    // insert variables into new object. Object will be made available to other functions
    $variables = new CEvent($this, array('var1'=>&$var1,'var2'=>&$this->id)); 
 
 
    $this->onAdd($variables);  // bookmark to insert custom functions 
                               // and avail variables to custom functions
    //statements that will add the data
  }
  public function onAdd($variables) // the bookmark must execute raiseEvent 
  {
    $this->raiseEvent('onAdd',$variables);  // all custom functions are executed here
  }
}
 
class SiteController extends CController
{
  public function actionIndex() // when page site/index is launched
  {
    $data=new Data; // initiate component
    $data->id=$id; 
    $data->onAdd = 'checkWhatItIs'; // add custom function
    $data->add('hello');
 
 
  }
}

For more info: http://www.yiiframework.com/forum/index.php/topic/3739-request-for-component-event-example/

#15075 report it
NetDaddi at 2013/10/05 01:52am
Under the Hood of Yii’s Component Architecture, Part 1

@RKK

Thanks for the example and the link. I would like to say the link is now a 3 part series and has a new URL Under the Hood of Yii’s Component Architecture, Part 1. If you are a newbie like I am it is very helpful.

#12967 report it
Barnabas Tso at 2013/04/23 11:18pm
@RKK

How I wish I saw you comment 3hrs ago. Best explanation on the web. thanks

#11290 report it
RKK at 2013/01/03 04:42pm
Events & Behaviors : Under the hood

Hey guys,

If you want to really be an expert in this "events & behaviors" stuff then I recommend you to read this useful, 3-part article, from PHP-Master:

Under the hood of Yii's component architecture

easy :)

#7189 report it
yugene at 2012/03/02 07:02am
addition to "Events in real life"

This is an addition to Events in real life comment.

First of all, I think this practical example is the best one I could find (thanks to http://blog.mbischof.de/yiiframework-events).

I'd like to add a couple of clarifications.

  1. The last two pieces of code you may put into your controller (this "somewhere" word confused me at first).
  2. As the second step you may try to move hello() and hello2() to components/TestObserver.php and notify them via
$model->onNewUser = array(new TestObserver(), 'hello');
$model->onNewUser = array(new TestObserver(), 'hello2');

in your controller (the last piece of code in "Events in real life")

#7135 report it
twisted1919 at 2012/02/26 06:07pm
@myView

You my friend deserve a medal :)

#6695 report it
Farzan at 2012/01/30 01:04am
Behaviors add both properties and methods to objects

Behaviors add both properties and methods to objects. They support getters and setters as well.

#6419 report it
fsb at 2012/01/09 09:23am
What about adding properties in a behavior?

The article makes it seem as if a behavior is only for adding methods. Is this the case?

#4912 report it
RKK at 2011/08/28 09:08am
Events in real life

I've looked anywhere to find a real life example of events but nothing... finally with help of google the examples found in a really useful blog (http://blog.mbischof.de/kategorie/yii/). it was not in English but again google helped me (+ some manual edits), have a try:

After a user registration can happen many things:

  • the administrator is informed
  • the registered user receives an email confirming
  • possibly a profile is initialized
  • a counter is incremented, etc.

Actions are executed when certain events occur (Observer Pattern) When a user registers, I want to execute certain actions.

I define a new event onNewUser in User-model:

public function onNewUser($event)
{
    $this->raiseEvent('onNewUser', $event);
}

which is executed after the record has been created:

public function afterSave()
{
    if ($this->isNewRecord) {
        if ($this->hasEventHandler('onNewUser')) {
            $event = new CModelEvent($this);
            $this->onNewUser($event);
        }
    }
 
    parent::afterSave();
}

in my controller, I can define actions to be executed then:

public function hello($event)
{
    $user = $event->sender;
    var_dump($user->firstname, $user->lastname);
}
 
public function hello2($event)
{
    $user = $event->sender;
    var_dump($user->email); exit;
}

and yet I need to attach these two actions to my onNewUser event:

public function actionCreate()
{
    $model = new User;
 
    if(isset($_POST['User'])) {
 
        $model->attributes = $_POST['User'];
 
        $model->onNewUser = array($this, 'hello');
        $model->onNewUser = array($this, 'hello2');
 
        if ($model->save()) {
            $this->redirect(array('show','id' => $model->id));
        }
    }
 
    $this->render('create', array('model' => $model));
}

As my friend mentioned in another comment in your projects you should use Events in a way that helps you make thing clean and faster. here we have seen just a simple example :)

Leave a comment

Please to leave your comment.

Write new article
  • Written by: pestaa
  • Updated by: Gismo
  • Category: Tutorials
  • Yii Version: 1.1
  • Votes: +50
  • Viewed: 88,464 times
  • Created on: Aug 24, 2009
  • Last updated: Jan 10, 2013