接上回,上次的更改小x经理很满意,但是提出了几点意见。
她是这样说的:
系统本地留log没必要弄个类,太麻烦了,日志也不需要记录具体人,有个时间即可。
管理员就一个人,不要用静态方法。
经理一定是处女座的,好吧,她的要求是对的,每个事件都是具有自己的用意,有的是一个对象,有的是系统级别,有的是一类东东,看来我要先复习一下yii的事件都能绑定什么了?
yii事件支持的绑定
前面说过yii一共能绑定四种类型的函数,分别是
全局函数
类的静态函数
对象的方法
匿名函数
支持的函数理解很简单,难在使用场景,这是我们要思考的。
@@nai8@@
针对小x经理说的第一个问题,我似乎用一个匿名函数就可以搞定了,于是我改了appcontrollersUserController.php 中对于OLog的绑定逻辑
use yii\web\User;
class UserController extends Controller {
public function __construct(){
// 绑定事件
$this->on(User::EVENT_AFTER_LOGIN,function($event){
$time = date("Y-m-d H:i:s");
Yii::info("有人在{$time}登陆了");
});
$this->on(User::EVENT_AFTER_LOGIN,['app\models\Admin','sendMail']);
$this->on(User::EVENT_AFTER_LOGIN,['app\models\User','notifyFirend']);
}
public function actionIndex(){
.....
// login
}
}
而对于小x经理的第二个需求,当有人登陆后将一个邮件发给一个管理员,那么应该是Admin实例化后的一个方法,看来这次我要改造Amdin观察者类了
开始改造
// Admin app\models\Admin.php
class Admin {
public function sendMail($event){
echo "我给管理员发了邮件";
}
}
我将sendMail的静态化去掉了,然后修改绑定的函数类型
use yii\web\User;
class UserController extends Controller {
public function __construct(){
// 绑定事件
$this->on(User::EVENT_AFTER_LOGIN,function($event){
$time = date("Y-m-d H:i:s");
Yii::info("有人在{$time}登陆了");
});
$admin = Admin::findOne(1); //管理员id为1
$this->on(User::EVENT_AFTER_LOGIN,[$admin,'sendMail']);
$this->on(User::EVENT_AFTER_LOGIN,['app\models\User','notifyFirend']);
}
public function actionIndex(){
.....
// login
}
}
接下来我准备提交本次小x给的任务,在提交前我们做一点事情,都知道on叫做绑定,trigger叫触发,那么上面这些订阅者的事件函数,我们给它们起个名字叫做 “事件处理器”,以后会用这个名字代表它们。
我是时间分隔线⛔️⛔️⛔️⛔️⛔️⛔️
事件处理器的顺序
10分钟后我回到了自己的位置,小x经理对本次修改很满意,但是她给了我另一个活,原话是这样:
小北啊,看来你对事件蛮有悟性的,我再给你一个事件的任务,帮你提高啊
我的心呀~拔凉拔凉的~
这次的任务如下:
晚24点到第二天6点,记录系统log,不要给客户和管理员发消息,客户要觉觉、管理员要觉觉。
政府说要监听每次登陆,上面的判断对政府监听不起作用,烦死它们。
对于政府的监听一直放到最前面,不受后续新增事件处理器影响,也不受将来程序员有可能勿调on代码顺序所影响。
听着很复杂,偶心中窃喜,yii已经提供了功能,我知道对于一个事件有多个事件处理器的时候,事件处理器执行的顺序和绑定顺序一致,并且yii提供了一个阻断机制,你可以对一个事件处理器执行阻断后,后面的所有事件处理器都不会再执行。
这个阻断机制就是event对象的handled,默认为假,不阻断。开始写代码
use yii\web\User;
class UserController extends Controller {
public function __construct(){
// 绑定事件
$this->on(User::EVENT_AFTER_LOGIN,function($event){
$time = date("Y-m-d H:i:s");
Yii::info("有人在{$time}登陆了");
if(时间在晚24点和第二天6点间){
$event->handled = true;
}
});
$admin = Admin::findOne(1); //管理员id为1
$this->on(User::EVENT_AFTER_LOGIN,[$admin,'sendMail']);
$this->on(User::EVENT_AFTER_LOGIN,['app\models\User','notifyFirend']);
}
public function actionIndex(){
.....
// login
}
}
你看到了把,就是一句简单的 $event->handled = true;就ok了。
接下来我们要添加政府订阅者,我们编写了一个叫做Gov的订阅者类,它有一个叫做notify的事件处理器,并且要让他的优先级最高。
上面我们说到了事件处理器执行的顺序和on绑定顺序一致,一种方法是将Gov的绑定放到绑定列表最前面,但是这样又不满足小x经理的第三条交代,好在yii已经有该功能了。
对于绑定函数on,存在着第四个参数,当你设置该参数为flase时,此事件处理器将进入到处理器列表最前端,开始干
use yii\web\User;
class UserController extends Controller {
public function __construct(){
// 绑定事件
$this->on(User::EVENT_AFTER_LOGIN,function($event){
$time = date("Y-m-d H:i:s");
Yii::info("有人在{$time}登陆了");
if(时间在晚24点和第二天6点间){
$event->handled = true;
}
});
$admin = Admin::findOne(1); //管理员id为1
$this->on(User::EVENT_AFTER_LOGIN,[$admin,'sendMail']);
$this->on(User::EVENT_AFTER_LOGIN,['app\models\User','notifyFirend']);
$this->on(User::EVENT_AFTER_LOGIN,['app\models\Gov','notify'],null,false);
}
public function actionIndex(){
.....
// login
}
}
这样一设置,因为它处于第一位,时间范围限制不了它,以后增加的其他事件处理器,只要我保证他们的第四个参数都不是flase,则Gov永远是第一位。
ok,阻断后续事件处理器的执行、人为影响事件处理器的执行顺序,我用这两个知识点解决了小x经理的需求。
开始 git
你以为这就完事了?还没有,下回告诉你git后的故事。
更多可以来我的yii原创视频小站 http://nai8.me
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。