The event and behaviour understanding in Yii

Source: Internet
Author: User
Tags inheritance yii

Event

Event is a complex and simple problem, because there are always many concepts easily interwoven, before understanding the event, we first need to understand the concept of event.

Event often has two characters, one is event, one is event Handler. Why do you need two?

The reason is easy to understand, the event just shows that this happened, but did not say how to deal with. This part of the work of course is left to the event handler.

I am here mainly from the similarity with the real world, do not involve the interpretation of design patterns. Interested friends can go to see the relevant mode, the data is still a lot of.

To get to the point, the concept of event and event handler must always be in the chest, otherwise, it is easy to confuse.

Here we analyze the situation in Yii mainly

For the understanding of the event in Yii, the first thing to know is that a few things

1. In Yii, the event is generally extended in ccomponet subclasses, generally starting with on.

Public Function OnClick ($event)
 {
     $this->raiseevent (' OnClick ', $event);
 }

The above is an example that defines the event. But you should be aware that the $event here is not the event we mentioned earlier, and that $event and this onclick function as a whole constitute an event,

This is also easy to understand, because the composition of an event requires a sign stating that event occurs, and some data is needed to illustrate what happened when the event occurred.

2, such as RaiseEvent mechanism to understand, is to see the source code.

We first look at the ccomponent RaiseEvent source code, of course, can not avoid the ccomponet of the source code

Before explaining RaiseEvent, we need to look at a piece of code in the Ccomponent, which is the __get function

Public Function __get ($name) {$getter = ' get '. $name;
                 if (Method_exists ($this, $getter)) return $this-> $getter (); else if (strncasecmp ($name, ' on ', 2) ===0 && method_exists ($this, $name)) {/
                         /duplicating Geteventhandlers () Here is for performance $name =strtolower ($name);
                         if (!isset ($this->_e[$name]) $this->_e[$name]=new CList;
                 return $this->_e[$name];
                 else if (isset ($this->_m[$name)) return $this->_m[$name];
                         else if (Is_array ($this->_m)) {foreach ($this->_m as $object) {if ($object->getenabled () && (Property_exists ($object, $name) || $object->cangeTproperty ($name)) return $object-> $name; } throw new CException (Yii::t (' Yii ', ' property ' {class}.{
         Property} ' are not defined. ', Array (' {class} ' =>get_class ($this), ' {property} ' => $name)); }

Here in fact, the function is very simple, that is, for different situations to complete the call to the $this->property operation, this should belong to PHP, do not say more.

The main thing we need to be aware of here is $this->_e[$name] This variable, in the 第6-13 line of the program, this is the action for the event.

Here, as far as it is clear, this variable is a clist type and is related to the specific event that is set.

Next, we can look at the specific RaiseEvent code, as follows:

Public Function RaiseEvent ($name, $event) {$name =strtolower ($name); if (Isset ($this->_e[$name])) {foreach ($this->_e[$name] as $handler) {if (Is_stri
             Ng ($handler)) Call_user_func ($handler, $event);
                     else if (is_callable ($handler, True)) {if (Is_array ($handler)) {
                     An array:0-object, 1-method Name list ($object, $method) = $handler;
                     if (is_string ($object))//static method call Call_user_func ($handler, $event);
                     else if (method_exists ($object, $method)) $object-> $method ($event); else throw new CException (Yii::t (' Yii ', ' Event ') {class}.{ Event} ' is attached with ' invalid handler ' {handler} '. ', Array (' {class} ' =>get_class ($thi s), ' {event} ' => $name, ' {handLer} ' => $handler [1]));
             else//PHP 5.3:anonymous function Call_user_func ($handler, $event); else throw new CException (Yii::t (' Yii ', ' Event ') {class}.{ Event} ' is attached with ' invalid handler ' {handler} '. ', Array (' {class} ' =>get_class ($this), ' {EV
             ENT} ' => $name, ' {handler} ' =>gettype ($handler))); Stop further handling if param.handled is set true if ($event instanceof CEvent) && $event->han
         dled) return; } else if (Yii_debug &&! $this->hasevent ($name)) throw new CException (Yii::t (' YII ', ' Event ') {class}.
 {event} ' is not defined. ', Array (' {class} ' =>get_class ($this), ' {event} ' => $name))); }

In the last line, we found the $this->_e[$name] variable, looking down from line fourth, it is not difficult to find that this variable is a place to store the event handler, is to put a specific way to deal with the events of the function.

There is a need for a section, you may be surprised, did not see the specific event handler incoming AH. I quote a ccomponent procedure to illustrate that

$component->onclick= $callback;    or $component->onclick->add ($callback);

See here, it's natural to think of finding the __set function in Ccomponet

Public Function __set ($name, $value) {$setter = ' set '. $name;
                 if (Method_exists ($this, $setter)) return $this-> $setter ($value); else if (strncasecmp ($name, ' on ', 2) ===0 && method_exists ($this, $name)) {/
                         /duplicating Geteventhandlers () Here is for performance $name =strtolower ($name);
                         if (!isset ($this->_e[$name]) $this->_e[$name]=new CList;
                 return $this->_e[$name]->add ($value); else if (Is_array ($this->_m)) {foreach ($this->_m as $ob ject) {if ($object->getenabled () && property_exists ( $object, $name) | | $object->cansetproperty ($name)) return $object-≫ $name = $value; } if (Method_exists ($this, ' get '. $name)) throw new CException (Y Ii::t (' Yii ', ' property ') {class}.{ Property} ' are read only. ', Array (' {class} ' =>get_class ($this), ' {property} ' => $name))
                 ); else throw new CException (Yii::t (' Yii ', ' property ') {class}.{ Property} ' isn't defined. ', Array (' {class} ' =>get_class ($this), ' {property} ' => $name
         ))); }

Looking from the sixth line, I found it. Again the relevant part of the event, see the 12th line, found it. The $callback is deposited into the $this->_e[$name] variable. Well, say here, we're going back to RaiseEvent ...

In fact, the next code is also easy to understand, is running this event handler. Some of the judgments in it are just for different forms of $callback.

Seems... The event part is finished ... There is nothing wrong in fact it is such a simple thing.

To sum up, is to first in the componet related subclass 1, defines the event, is the ONXXX function. (The above is only done at the time of definition, the next can be defined in the definition, can also be dynamically processed according to the situation.) 2, the need to give the corresponding EventHandler is Callback3, invoke the corresponding event, is in you think that will appear this event place to join this event function, you can. For example, in the beginning of a click function, put the onclick, indicating that before the click action is performed.

Behaviour

Behaviour Chinese name is behavior, then what is he exactly? What's the relationship with the event?

In fact, in Yii, this behaviour is another manifestation of event handler, which is one thing that we said before $callback, just to expand and use, and do further encapsulation.

Before we explain behaviour, we must understand a concept mixin ... This is not "superstition" means. I think it's a mix in, but I'm not sure what it is, he's actually nothing, it's a concept.

What does this concept specifically mean. Refers to a class that provides a function that can be inherited or reused by its subclasses without instantiating it. For general languages, only single inheritance is possible, and mixin behaves more like multiple inheritance. He emphasized that inheritance from Mixin was not a feature, but a means of collecting functions. It's amazing. It's very obscure, too. It's actually the algorithm. We are easy to understand in a concrete instance.

Next we look at the implementation of Yii, first of all look at the use of behaviour method.

$name uniquely identifies
the behavior in the component $component->attachbehavior ($name, $behavior);
Test () is $behavior
$component->test ();

Above by invoking the association of the Attachbehavior Method implementation in Ccomponet, we drill down into the source code to see what is actually done.

Public Function Attachbehavior ($name, $behavior)
 {
     if (!) ( $behavior instanceof Ibehavior))
         $behavior =yii::createcomponent ($behavior);
     $behavior->setenabled (true);
     $behavior->attach ($this);
     return $this->_m[$name]= $behavior;
 }

The program is very short, is to judge the incoming behaviour is not a ibehavior instance, according to the situation to do some processing, anyway, finally by calling the Ibehavior attach method to hang to the current Ccomponent method.

Okay, here's the key. Note that the seventh line, there is no mistake, the incoming behavior passed into the $this->_m[$name] variable, which is why many binding reasons, to achieve the mechanism of collection.

You should have noticed that I missed a key point here, the sixth line. This part is the core of mixin. Let's go to Ibehavior to see the method definition first.

/** * Ibehavior interfaces is implemented by all behavior classes. * * A behavior is a way to enhance a component with additional methods, that * are defined in the behavior class and No
  T available in the component class. * * @author Qiang xue <qiang.xue@gmail.com> * @version $Id $ * @package system.base * @since 1.0.2/inte
          Rface Ibehavior {/** * Attaches the behavior object to the component.
 * @param the Ccomponent $component the component that this behavior are to being attached to.
         * * Public Function attach ($component);
          /** * detaches the behavior object from the component.
 * @param ccomponent $component The component that this behavior are to being detached from.
         * * Public Function detach ($component);
         /** * @return Boolean whether this behavior is enabled */Public function getenabled (); /** * @param boolean $value Whether this behavior is Enabled */Public Function setenabled ($value); }

Mainly see attach method, he is a behavior bound to component a method, concrete implementation in its subclass, we continue to look, see Cbehavior

For the implementation of attach, the following

Public function Attach ($owner)
{
    $this->_owner= $owner;
    foreach ($this->events () as $event => $handler)
        $owner->attacheventhandler ($event, Array ($this, $handler ));
}

Detailed analysis of this code, here is done, set the behavior binding object, which means that a behavior object can only be a component service, the so-called collection function is mainly described in the previous $this->_m[$name] role.

Then the event and behavior how can have a relationship. See $owner->attacheventhandler ($event, Array ($this, $handler)); $owner is the component that we bind behavior, it is easy to find the binding function of the event handler implemented here with the name of the method.

Here's what the $this->events () is.

Public function events ()
        {return
                array ();
        }

I can't match up with the above. Returned an empty array ()? Don't get it wrong, this function you can think of as a virtual function that needs to be rewritten. You can actually understand here. The events () method returns an associative array that contains the event name and event-handling methods.

If we can not understand, we look at the specific implementation of the Cmodelbehavior, he inherited from Cbehavior.

Public function events ()
{return
    array (
        ' onafterconstruct ' => ' afterconstruct '),
        ' Onbeforevalidate ' => ' beforevalidate ',
        ' onaftervalidate ' => ' aftervalidate ',
    );


Did you see it? Three events are defined, as well as corresponding event handlers, but these event-handling functions need to be rewritten as you expand.

Back to the behavior Attach method $owner->attacheventhandler ($event, Array ($this, $handler);

Let's go in and see what the Attacheventhandler method in this componet is all about.

Public Function Attacheventhandler ($name, $handler)
         {
                 $this->geteventhandlers ($name)->add ($handler) ;
         }
 
         Public Function Geteventhandlers ($name)
         {
                 if ($this->hasevent ($name))
                 {
                         $name =strtolower ($name );
                         if (!isset ($this->_e[$name])
                                 $this->_e[$name]=new CList;
                         return $this->_e[$name];
                 }
                 else
                         throw new CException (Yii::t (' Yii ', ' Event ') {class}.{ Event} ' is not defined. ',
                                 Array (' {class} ' =>get_class ($this), ' {event} ' => $name));
         }

The Geteventhandlers method is called in the Attacheventhandler method, which is to return the $this->_e[$name] variable, and then $handler into the deposit, note here the $ Handler actually corresponds to the array ($this, $handler) at the call.

All of this is obvious in the context of what was said in the previous event.

To sum up, behavior can actually be considered as a sort of classification of events, grouped together, and then registered together, which is easier to maintain and manage, but also more object-oriented. So behavior can also be considered a collection of events and their processing methods.


Ok, go around and finally get around. In fact, the whole is still very simple. But this idea is good, let behavior let the event also can reuse, or can say that the type of event can be conveniently categorized.
Author: Anykoro Origin: http://JosephLiu.cnblogs.com/




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.