今天主要熟悉了yii框架的事件处理器
yii框架的事件可以将自定义代码“注入”到现有代码中的特定执行点。 附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行。 例如,邮件程序对象成功发出消息时可触发 messageSent 事件。 如想追踪成功发送的消息,可以附加相应追踪代码到 messageSent 事件。
Yii 引入了名为 yii\base\Component 的基类以支持事件。 如果一个类需要触发事件就应该继承 yii\base\Component 或其子类。
首先事件处理器是一个php回调函数,当它所附加的事件被触发时它就会执行。可以使用以下回调函数之一。
- 字符串形式指定的 PHP 全局函数,如 ‘trim’ ;
- 对象名和方法名数组形式指定的对象方法,如 [$object, $method] ;
- 类名和方法名数组形式指定的静态类方法,如 [$class, $method] ;
- 匿名函数,如 function ($event) { … } 。
事件的处理格式是:
function ($event) {
// $event 是 yii\base\Event 或其子类的对象 }
通过 $event 参数,事件处理器就获得了以下有关事件的信息:
- event name:事件名
- event sender:调用 trigger() 方法的对象
- custom data:附加事件处理器时传入的数据,默认为空,后文详述
附加事件处理器(Attaching Event Handlers)
调用 yii\base\Component::on() 方法来附加处理器到事件上。如:
$foo = new Foo;
// 处理器是全局函数
$foo->on(Foo::EVENT_HELLO, 'function_name');
// 处理器是对象方法
$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']);
// 处理器是静态类方法
$foo->on(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);
// 处理器是匿名函数
$foo->on(Foo::EVENT_HELLO, function ($event) {
//事件处理逻辑
});
事件处理器顺序(Event Handler Order)
可以附加一个或多个处理器到一个事件。当事件被触发,已附加的处理器将按附加次序依次调用。 如果某个处理器需要停止其后的处理器调用,可以设置 event 参数的 yii\base\Event::$handled 属性为真, 如下:
$foo->on(Foo::EVENT_HELLO, function ($event) {
$event->handled = true;
});
默认新附加的事件处理器排在已存在处理器队列的最后。 因此,这个处理器将在事件被触发时最后一个调用。 在处理器队列最前面插入新处理器将使该处理器最先调用,可以传递第四个参数 $append 为假并调用 yii\base\Component::on() 方法实现:
$foo->on(Foo::EVENT_HELLO, function ($event) {
// 这个处理器将被插入到处理器队列的第一位...
}, $data, false);
触发事件(Triggering Events)
事件通过调用 yii\base\Component::trigger() 方法触发,此方法须传递事件名, 还可以传递一个事件对象,用来传递参数到事件处理器。如:
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);
}
}
以上代码当调用 bar() ,它将触发名为 hello 的事件。
有时想要在触发事件时同时传递一些额外信息到事件处理器。 例如,邮件程序要传递消息信息到 messageSent 事件的处理器以便处理器了解哪些消息被发送了。 为此,可以提供一个事件对象作为 yii\base\Component::trigger() 方法的第二个参数。 这个事件对象必须是 yii\base\Event 类或其子类的实例。 如:
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)
{
// ...发送 $message 的逻辑...
$event = new MessageEvent;
$event->message = $message;
$this->trigger(self::EVENT_MESSAGE_SENT, $event);
}
}
当 yii\base\Component::trigger() 方法被调用时, 它将调用所有附加到命名事件(trigger 方法第一个参数)的事件处理器。
移除事件处理器(Detaching Event Handlers)
从事件移除处理器,调用 yii\base\Component::off() 方法。如:
// 处理器是全局函数
$foo->off(Foo::EVENT_HELLO, 'function_name');
// 处理器是对象方法
$foo->off(Foo::EVENT_HELLO, [$object, 'methodName']);
// 处理器是静态类方法
$foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);
// 处理器是匿名函数
$foo->off(Foo::EVENT_HELLO, $anonymousFunction);
注意当匿名函数附加到事件后一般不要尝试移除匿名函数, 除非你在某处存储了它。以上示例中, 假设匿名函数存储为变量 $anonymousFunction 。
移除事件的全部处理器,简单调用 yii\base\Component::off() 即可,不需要第二个参数:
$foo->off(Foo::EVENT_HELLO);