Yii2 事件学习笔记
Yii2中事件一般用event表示,只有集成了yii\base\component的对象才能集成类或者对象级别的事件处理过程。
事件的理解和使用要点主要有以下几个要点:
1.事件如何触发?
2.事件处理器是什么?
3.事件级别分为哪几个?
4.如何把事件处理器(handle)绑定到事件上?
5.如何解绑handle?
6.事件处理器的执行顺序?
7.事件常见用途
1.事件触发
调用 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);
}
}
2.事件处理器 Event Handlers
事件处理器是一个PHP 回调函数,参数是一个event对象。
下面复习一下回调函数的一般写法:
①.匿名函数 function($event){
}
②.某个对象的方法
[$obj,'方法名称']
③.类的静态防范
[static::className(),'静态方法名']
④.全局函数,这种情况比较少一点,
'全局方法名'
3.事件级别
官方文档没有强调这个,可以大致分为3个级别:
①对象级别,对于某个对象的事件触发,参考1中的例子
②类级别事件处理,
如果想对某一类对象不想一个个的附加事件处理,可以在类级别直接绑定,使用方法如下。
调用yii\base\Event的on方法
Event::on(静态类名,静态类事件,事件处理器);
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');
});
③全局事件绑定以及处理
全局应用即Yii::$app,全局应用是个单例对象,可以使用对象的事件绑定方法
第一步,在应用入口脚本:
Yii::$app->on('bar', function ($event) {
echo get_class($event->sender); // 显示 "app\components\Foo"
});
第二步:埋点,在需要的地方进行触发
Yii::$app->trigger('bar', new Event(['sender' => new Foo]));
这里的触发器的第二个参数表示可以定义事件对象的一些属性,
name:事件名
sender:调用 trigger() 方法的对象
data:附加事件处理器时传入的数据,默认为空
4.如何把事件处理器(handle)绑定到事件上?
一般而言,调用类或者对象的on方法即可,但是对于类或者对象的on方法的参数会有一些不一样。
5.如何解绑handle?
解绑发方法为off,与4中on的使用类似。
6.事件处理器的执行顺序?
事件处理器将按附加次序依次调用,默认新附加的事件处理器排在已存在处理器队列的最后。
特殊情况如果需要优先调用则可以在on函数中传递第四个参数为false,即可第一个调用。如下所示:
$foo->on(Foo::EVENT_HELLO, function ($event) {
// 这个处理器将被插入到处理器队列的第一位...
}, $data, false);
7.经典用法
事件的用途比较多,常见的用途是记录日志,
如记录全局的代码级别的操作日志,数据库的更新操作日志等等。
①记录全局访问日志的写法:
在配置文件中假如如下配置: 'on beforeRequest' => handle;
②记录数据库更新操作
第一步,在配置文件新增行为配置:'as adminLog' => 'app\\behaviors\\AdminDbLogBehavior';
第二部,在yii\db\command类中埋点,比如在execute中:
const EVENT_EXECUTE = 'execute';
public function execute()
{
$this->trigger(self::EVENT_EXECUTE);
.....other code
}
第三步,在AdminDbLogBehavior.php中进行事件绑定,并指定事件处理器,在事件处理器中进行具体的记录操作,代码类似如下:
namespace frontend\behaviors;
use Yii;
use yii\base\Application;
use yii\base\Behavior;
use yii\base\Event;
use yii\db\Command;
class AdminLogBehavior extends Behavior
{
public function events()
{
return [
Application::EVENT_BEFORE_REQUEST => 'handle'
];
}
public function handle()
{
Event::on(Command::className(), Command::EVENT_EXECUTE,[$this,'log']);
}
public function log($event)
{
//具体的记录操作,
//如果是记录db更新操作那么不要直接记录到当前数据库,否则会引起循环记录
}
}