In-depth analysis of the event mechanism in PHP's Yii framework, yiievent_php tutorial

Source: Internet
Author: User

In-depth analysis of the event mechanism in PHP's Yii framework, yiievent

Events can "inject" custom code into specific execution points in existing code. Add custom code to an event, and the code executes automatically when the event is triggered. For example, a mail program object can trigger a Messagesent event when it successfully emits a message. If you want to track messages that have been sent successfully, you can attach the corresponding tracking 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, reasonable use of the event mechanism, will make the coupling between the components more loose, conducive to group collaborative development.
When to use events, how to bind event handlers to events, and how to trigger events, is a big difference from other languages. For example, in JavaScript, you can use

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

The function is bound to the DOM element, and is automatically executed when the specified event (such as click) occurs on the DOM element.
But PHP is the server-side scripting language, there is no automatic triggering events, so in contrast to JavaScript, Yii events are required to be triggered manually. In general, to implement the event mechanism for YII components requires the following steps:

Defining an event name is actually a level component that defines a method on the start, where the code is fixed, such as:

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

That is, the function name is consistent with the event name. The purpose of this step is to execute the handler functions bound on this event one by one. Write this series of podcasts, sort of a collation, so I write a little bit, now the RaiseEvent method of the code to paste out.

/** * raises an event. * This method represents the happening of an 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 U Ndefined or an event handler is invalid.         */Public Function RaiseEvent ($name, $event) {$name =strtolower ($name);                 _e This array is used to store 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-ob                      ject, 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->hand             LED) 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 is attached to is triggered. You can use one of the following callback functions:

    • A PHP global function specified as a string, such as ' trim ';
    • Object names and methods an array object methods specified in the form of a group, such as [$object, $method];
    • Class names and methods an array static class methods as specified in the 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: Object that calls the trigger () method
    • Yii\base\event::d ATA: Data passed in when the event handler is attached, default is empty, later in detail

Additional event handlers

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

$foo = new foo;//processor is a global function $foo->on (Foo::event_hello, ' function_name ');//Processor is an object method $foo->on (Foo::event_hello, [$ Object, ' MethodName ');//processor is static class method $foo->on (Foo::event_hello, [' App\components\bar ', ' methodName ']);//Processor is anonymous function $ Foo->on (Foo::event_hello, function ($event) {  //Event handling Logic}), additional data can be supplied as yii\base\component::on () when attaching an event handler The third parameter of the method. The data can be used by the processor when the event is triggered and the processor is called. such as://When the event is triggered the following code shows "ABC"//Because the $event->data includes data $foo->on (Foo::event_hello, function ($event) that is passed to the "on" method {  echo $event->data;}, ' abc ');

Event handler Order

You can attach one or more processors to an event. When an event is triggered, the attached processor is called sequentially in an additional order. 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, the processor will be the last call when the event is triggered. Inserting a new processor at the front of the processor queue will make the processor the first call, passing the fourth parameter $append false and calling the Yii\base\component::on () method implementation:

$foo->on (Foo::event_hello, function ($event) {  //This processor will be plugged into the first bit of 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 can pass an event object that passes 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);  }}

When the above code calls bar (), it will trigger the event named Hello.

Tip: It is recommended to use class constants to represent event names. In the example above, the constant Event_hello is used to denote HELLO. This has two benefits. First, it prevents spelling errors and supports automatic completion of the IDE. Second, simply check the constant declaration to see which events are supported by a class.
Sometimes you want to pass some extra information to the event handler while triggering the event. For example, the mail program will pass the message information to the processor of the Messagesent event so that the processor knows which messages were 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 $message logic    ... $event = new Messageevent;    $event->message = $message;    $this->trigger (self::event_message_sent, $event);}  }

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

Removing event handlers

Removes the processor from the event, calling the Yii\base\component::off () method. Such as:

The processor is the global function $foo->off (Foo::event_hello, ' function_name ');//The processor is the object method $foo->off (Foo::event_hello, [$object, ' MethodName ']);//Processor is a static class method $foo->off (Foo::event_hello, [' App\components\bar ', ' methodName ']);//processor is an anonymous function $foo- >off (Foo::event_hello, $anonymousFunction);

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

Remove the entire processor of the event, simply call Yii\base\component::off () and do not need a second parameter:

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

Class-level event handlers

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

For example, an activity 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 activity 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 ');});

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

When an object fires an event, it invokes the processor at the instance level first, and then the class-level processor is called.

A static method Yii\base\event::trigger () can be called to trigger a class-level event. Class-level events are not associated with a particular object. Therefore, it only causes a call to the class-level event handler. Such as:

Use yii\base\event; Event::on (Foo::classname (), Foo::event_hello, function ($event) {  echo $event->sender;//Show "App\models\foo"}) ; Event::trigger (Foo::classname (), Foo::event_hello);

Note In this case $event->sender points to the class name that triggered the event instead of the object instance.

Note: Because the class-level processor responds to events that are triggered by all instances of the class and its subclasses, you must use caution, especially the underlying base class, such as Yii\base\object.
Removing event handlers at the class level simply calls Yii\base\event::off (), such as:

Remove $handlerEvent:: Off (Foo::classname (), Foo::event_hello, $handler),//Remove all processor Event::off for Foo::event_hello events (Foo: : ClassName (), Foo::event_hello);

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 singleton to trigger the global event. Similarly, the event handler is attached to the singleton 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 a global event is that it does not need to be produced when attaching a processor to an event to be triggered by an object. Instead, processor attach and event firings are done through a single example, such as an application instance.

However, because the namespace of global events is shared by all parties, it should be reasonable to name global events such as introducing some namespaces (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 to bind multiple callback functions, and the two methods above will add a new callback function to an existing event without overwriting the existing callback function.
$handler is a PHP callback function, the form of the callback function, the end of this article will be accompanied by a description. As in the Init event for the Clogrouter component, the following code is available:

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

This is the onendrequest bound to the CApplication object clogrouter: The:p rocesslogs () callback function. The CApplication component does have a method named Onendrequest (that is, the Onendrequest event), and the code in it is the activation of the corresponding callback function, the Clogrouter::p rocesslogs () method. So it can be concluded from here that the log records are actually occurring when the capplication component exits normally.

When a trigger event is required, the event of the component is activated directly, that is, the event can be invoked, such as in the Run method of the CApplication component:

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

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

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

Call_user_func (' print ', $str);

The static method of the class, using the array form to pass

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

Object methods, which are passed in array form

$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);


The event mechanism for Yii actually provides a way to decouple, before calling the event, as long as you provide the implementation of the events and register them in the place where they are needed.

Articles you may be interested in:

    • The method of removing the binding behavior of a component in PHP's YII framework
    • The definition and binding methods of behavior in the YII framework of PHP
    • A detailed approach to using behavioral behaviors in the PHP yii framework
    • In-depth explanation of properties in the Yii framework of PHP
    • PHP's YII framework uses database configuration and SQL Operations example tutorials
    • Full interpretation of the log function in the YII framework of PHP
    • Yii uses find FindAll to find out how to implement a specified field
    • Analysis and modification of yii database by adding and deleting
    • YII PHP Framework Practical Introductory Tutorial (detailed)
    • Attribute injection and method injection of component behavior in PHP's YII framework true techarticle in-depth parsing of the event mechanism in PHP's YII framework, Yiievent event events can "inject" custom code into specific execution points in existing code. Attaching custom code to something ...

  • 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: 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.