Deep analysis of event events in PHP's Yii framework _php tips

Source: Internet
Author: User
Tags constant static class first row yii

Event
events can "inject" custom code into specific execution points in existing code. Attach custom code to an event, and the code executes automatically when the event is triggered. For example, a messagesent event can be triggered when a mail program object successfully emits a message. To track successfully sent messages, you can attach the corresponding trace code to the Messagesent event.
Yii introduces a base class named Yii\base\component to support events. If a class needs to trigger an event, it should inherit yii\base\component or its subclasses.

The event mechanism of Yii
the event mechanism of YII is its unique place, the reasonable use of good event mechanism, will make the coupling between the various components more loose, conducive to group collaborative development.
When you need to use events, how to bind event handlers to events, and how to trigger events, are significantly different from other languages. For example, in JavaScript, you can use the

$ (' #id '). On ("click", Function () {});

method to bind a DOM element to a handler function that is automatically executed when a specified event occurs on a DOM element, such as Click.
But PHP is a server-side scripting language, there is no automatic trigger event, so in contrast to JavaScript, the events in Yii need to be triggered manually. In general, to implement the event mechanism for a YII component, the following steps are required:

The definition of an event name, in fact, is that the level component defines a method on the beginning of which the code is fixed, such as:

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

The

is that the function name is the same as the event name. The purpose of this step is to execute the processing functions that are bound on this event one by one. Writing this series of podcasts is a sort of collation, so I write a little bit and now post the code for the RaiseEvent method.

/** * raises an event. * This method represents the happening of the event. 
  It invokes * All attached handlers for the event.  * @param string $name The event name * @param CEvent $event the event parameter * @throws CException if the event is 
Undefined or a event handler is invalid.  
       * * Public Function RaiseEvent ($name, $event) {$name =strtolower ($name);     
            _e this array to save all event information if (Isset ($this->_e[$name]) {foreach ($this->_e[$name] as $handler) {       
            if (is_string ($handler)) Call_user_func ($handler, $event); ElseIf (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);     
 ElseIf (Method_exists ($object, $method))                    $object-> $method ($event); else throw new CException (Yii::t (' Yii ', ' Event ') {class}.{ Event} ' is attached with an invalid handler ' {handler} '. ', Array (' {class} ' =>get_class ($this), ' {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 an invalid handler ' {handler} '. ', Array (' {class} ' =>get_class ($this), ' {event} ' => $name, ' {     
           Handler} ' =>gettype ($handler))); Stop further handling if param.handled is set true if ($event instanceof CEvent) && $event->han   
          dled) return; } elseif (Yii_debug &&! $this->hasevent ($name)) throw new CexcePtion (yii::t (' Yii ', ' Event ') {class}.{
 Event} "is not defined.", Array (' {class} ' =>get_class ($this), ' {event} ' => $name)));

 }

event handler (handlers)

The event handler is a PHP callback function that executes when the event it attaches to is triggered. You can use one of the following callback functions:

    • The PHP global function specified in the string form, such as ' trim ';
    • Object names and methods, such as [$object, $method], specified by the array group form;
    • A static class method specified by the class name and method array group form, such as [$class, $method];
    • Anonymous functions, such as function ($event) {...}.

The format of the event handler is:

function ($event) {
  //$event is an object of yii\base\event or its subclasses
}

By $event parameters, the event handler obtains the following information about the event:

    • Yii\base\event::name: Event Name
    • Yii\base\event::sender: The object that invokes the trigger () method
    • Yii\base\event::d ATA: The data passed in when attaching an event handler is null by default, and the following text details

Attach event handler

Call the Yii\base\component::on () method to attach the processor to the event. Such as:

$foo = new Foo;

The processor is a global function
$foo->on (Foo::event_hello, ' function_name ');

The processor is an object method
$foo->on (Foo::event_hello, [$object, ' MethodName ']);

The processor is a static class method
$foo->on (Foo::event_hello, [' App\components\bar ', ' methodname ']);

The processor is an anonymous function
$foo->on (Foo::event_hello, function ($event) {
  //Event handling Logic
});
Additional data can be supplied as the third parameter of the Yii\base\component::on () method when attaching an event handler. The data can be used by the processor when the event is triggered and the processor is invoked. such as:

//When the event is triggered, the following code displays "ABC"
//Because $event->data includes data that is passed to the "on" Method
$foo->on (Foo::event_hello, function ($event) {
  echo $event->data;
}, ' abc ');

Event Processor Order

You can attach one or more processors to an event. When an event is triggered, the attached processor is called in the order in which it is attached. If a processor needs to stop subsequent processor calls, you can set the [Yii\base\event::handled] property of the $event parameter to True, as follows:

$foo->on (Foo::event_hello, function ($event) {
  $event->handled = true;
});

The default new attached event handler is ranked at the end of the existing processor queue. Therefore, this processor will be invoked the last time the event is triggered. Inserting a new processor at the top of the processor queue causes the processor to call first, passing the fourth parameter $append false and invoking the Yii\base\component::on () method implementation:

$foo->on (Foo::event_hello, function ($event) {
  //This processor will be inserted first in the processor queue ...
}, $data, false);


Triggering events

The event is triggered by calling the Yii\base\component::trigger () method, which passes the event name and passes an event object to pass the parameter to the event handler. Such as:

namespace App\components;

Use yii\base\component;
Use yii\base\event;

Class Foo extends Component
{
  const Event_hello = ' HELLO ';

  Public Function bar ()
  {
    $this->trigger (Self::event_hello);
  }


The above code, when called Bar (), triggers an event named Hello.

Tip: It is recommended that you use class constants to represent event names. In the example above, the constant Event_hello is used to represent HELLO. This has two advantages. First, it protects against spelling errors and supports automatic completion of the IDE. Second, simply checking the constant declaration allows you to understand which events a class supports.
Sometimes you want to pass some extra information to the event handler while the event is triggered. For example, the mail program passes message information to the Messagesent event's processor so that the processor knows which messages have been sent. To do this, you can provide an event object as the second parameter of the Yii\base\component::trigger () method. This event object must be an instance of the Yii\base\event class or its subclasses. Such as:

namespace App\components;

Use yii\base\component;
Use yii\base\event;

Class Messageevent extends Event
{public
  $message;
}

Class Mailer extends Component
{
  const event_message_sent = ' messagesent ';

  Public function Send ($message)
  {
    //... Send the logic

    of the $message ... $event = new Messageevent;
    $event->message = $message;
    $this->trigger (self::event_message_sent, $event);
  }


When the Yii\base\component::trigger () method is invoked, it invokes all event handlers that are attached to the named event (the first parameter of the trigger method).

Removing event handlers

Remove the processor from the event and invoke the Yii\base\component::off () method. Such as:

The processor is a global function
$foo->off (Foo::event_hello, ' function_name ');

The processor is an object method
$foo->off (Foo::event_hello, [$object, ' MethodName ']);

The processor is a static class method
$foo->off (Foo::event_hello, [' App\components\bar ', ' methodname ']);

The processor is an anonymous function
$foo->off (Foo::event_hello, $anonymousFunction);

Note When an anonymous function is attached to an event, do not attempt to remove the anonymous function, unless you store it somewhere. In the example above, assume that the anonymous function is stored as a variable $anonymousfunction.

Remove all the handlers for the event, simply call Yii\base\component::off () and do not need a second argument:

$foo->off (Foo::event_hello);

Class-level event handlers

In the above section, we describe how to attach a processor to an event at the instance level. Sometimes you want all instances of a class, rather than a specified instance, to respond to a triggered event, instead of attaching the event handler to each instance, but by calling the static method Yii\base\event::on () to attach the processor at the class level.

For example, an active Record object will trigger a Yii\db\baseactiverecord::event_after_insert event each time a new record is added to the database. To track the completion of new records for each active Record object, write the following code:

Use Yii;
Use yii\base\event;
Use Yii\db\activerecord;

Event::on (Activerecord::classname (), Activerecord::event_after_insert, function ($event) {
  yii::trace (get_ Class ($event->sender). ' is inserted ');


The event handler executes whenever an instance of Yii\db\baseactiverecord or its subclass triggers a Yii\db\baseactiverecord::event_after_insert event. In this processor, you can get the object that triggers the event by $event->sender.

When an object triggers an event, it first invokes the instance-level processor before calling the class-level processor.

static method Yii\base\event::trigger () can be invoked to trigger a class-level event. Class-level events are not associated with specific objects. Therefore, it will only cause calls to class-level event handlers. Such as:

Use yii\base\event;

Event::on (Foo::classname (), Foo::event_hello, function ($event) {
  echo $event->sender;//display "App\models\foo" c10/>});

Event::trigger (Foo::classname (), Foo::event_hello);

Note that in this case $event->sender point to the class name of the triggering event rather than the object instance.

Note: Events triggered by class-level processor response classes and all instances of their subclasses must be used with caution, especially at the underlying base class, such as Yii\base\object.
Removing a class-level event handler simply calls Yii\base\event::off (), such as:

Removal of $handler
Event::off (Foo::classname (), Foo::event_hello, $handler);

Remove all processors
Event::off (Foo::classname (), Foo::event_hello) of the Foo::event_hello event;

Global events

The so-called global event is actually a trick based on the event mechanism described above. It requires a globally accessible singleton, such as an application instance.

Instead of calling its own trigger () method, the event trigger invokes the trigger () method of the single instance to trigger the global event. Similarly, an event handler is attached to a single instance of an event. Such as:

Use Yii;
Use yii\base\event;
Use App\components\foo;

Yii:: $app->on (' Bar ', function ($event) {
  echo get_class ($event->sender);//Show "App\components\foo"
} );

Yii:: $app->trigger (' Bar ', New Event ([' Sender ' => new Foo]);

One advantage of global events is that when attaching a processor to an event that an object is to trigger, it does not need to produce the object. Instead, processor additions and event firings are done through a single example, such as an application instance.

However, because global event namespaces are shared by all parties, global events should be reasonably named, such as introducing namespaces (for example, "Frontend.mail.sent", "backend.mail.sent").

To bind an event handler to a Component object

$component->attacheventhandler ($name, $handler);
$component->onbeginrequest = $handler;

Yii supports an event-bound multiple callback functions, and the above two methods add new callback functions to existing events without overwriting existing callback functions.
$handler is a PHP callback function, the form of a callback function, which is illustrated at the end of this article. For example, the Init event for the Clogrouter component has the following code:

Yii::app ()->attacheventhandler (' Onendrequest ', Array ($this, ' processlogs '));

This is the onendrequest bound to the CApplication object clogrouter::p rocesslogs () callback function. The CApplication component does have a method named Onendrequest (that is, the Onendrequest event) in which the code activates the corresponding callback function, that is, the Clogrouter::p the Rocesslogs () method. So it can be concluded from here that the log records actually occur when the CApplication component's normal exit.

When an event needs to be triggered, directly activates the component's event, that is, invoking the event, such as: In the CApplication component's Run method:

if ($this->haseventhandler (' OnBeginRequest '))
  $this->onbeginrequest (New CEvent ($this));

This triggers the event handler function. If the first row is not judged, then in debug mode (the Yii_debug constant is defined to be true), an exception is thrown, and in the non-debug mode (the Yii_debug constant is defined as false or the Yii_debug constant is not defined), no exception is generated.
The form of the callback function:

Normal global functions (built-in or user-defined)

Call_user_func (' print ', $str);

Class by using the array form to pass a static method of the

Call_user_func (Array (' ClassName ', ' print '), $str);

Object method that uses an array form to pass the

$obj = new ClassName ();
Call_user_func (Array ($obj, ' print '), $str);

Anonymous methods, JavaScript-like anonymous functions

Call_user_func (function ($i) {echo $i ++;},4);

Or use the following form:

$s = function ($i) {
  echo $i + +;
};
Call_user_func ($s, 4);

Summarize

The event mechanism for YII is to provide a way of decoupling, which can be invoked as long as you provide the implementation of the event and register it when needed in the next place, before you need to invoke it.

Related Article

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.