-
Notifications
You must be signed in to change notification settings - Fork 1.6k
添加事件
先来看下官方文档是怎么样描述事件的。
新版的事件系统可以看成是5.1版本行为系统的升级版,事件系统相比行为系统强大的地方在于事件本身可以是一个类,并且可以更好的支持事件订阅者。
事件相比较中间件的优势是事件比中间件更加精准定位(或者说粒度更细),并且更适合一些业务场景的扩展。例如,我们通常会遇到用户注册或者登录后需要做一系列操作,通过事件系统可以做到不侵入原有代码完成登录的操作扩展,降低系统的耦合性的同时,也降低了BUG的可能性。
官方文档提供的操作方法有:
//直接使用事件类触发
Event::trigger('UserLogin');
//动态绑定
Event::bind(['UserLogin' => 'app\event\UserLogin']);
//手动注册监听
Event::listen('UserLogin', 'app\listener\UserLogin');
事件触发之前是需要注册事件监听的。
也就是说使用Event::trigger之前需要Event::listen注册事件的监听
我们只有了解了事件的真正意义,才能更好运用事件,下面我将从实际场景出发,教大家如何添加事件。 在正常工作中应该很容易遇到这样的问题:
今天做一个用户登录模块,用户的需求就是简单的用户登录,登录完成以后不需要其他操作。然后作为码农的你很开心的写起了代码,很快就完成了。
第二天,用户又提出了新的需求,用户登录以后需要把用户登录次数增加,并且记录下用户的登录IP。然后码农的你还是很开新的写起了代码,这个也简单,很快的完成了。
第三天,用户又又来了。用户登录以后如果不是常用IP地址给用户发个邮件提醒下账号存在风险。 第四天,用户登录以后如果不是常用IP地址给用户发个邮件并且发送短信提醒下账号存在风险。 …… 一个月以后,你的控制器,你的逻辑,不敢想象……
这个时候事件就是一个很好的解决方案。
下面是一个超级简单的事件用法。 首先是Model,定义了一个方法,获取用户ID为1的用户信息。大家一定要注意,我本来应该遵循框架seervices层调用dao层,dao层调用model层,最后将services层注入到事件类中,但是为了更直观更容易理解,我实例时直接将model实例注入,大家开发时请严格按照顺序。
namespace app\model;
use think\Model;
class User extends Model
{
//获取用户ID为1的用户信息
public function getUserInfo()
{
return self::where('id', 1)->find();
}
}
然后用php think make:event User生成了一个User事件类,构造函数依赖注入UserModel;setLoginCount方法用于用户登录完成以后给用户登录次数+1(不要在意这个地方合不合理๑乛◡乛๑)。
namespace app\event;
use app\model\User as UserModel;
class User
{
public $user;
public function __construct(UserModel $user)
{
$this->user = $user;
}
//给用户登录次数+1
public function setLoginCount()
{
$userInfo = $this->user->getUserInfo();
$userInfo->login_count += 1;
return $userInfo;
}
}
定义了一个事件监听类User
namespace app\listener;
class User
{
public function handle(\app\event\User $event)
{
$userInfo = $event->user->getUserInfo();
echo 'listen监听器输出:' . json_encode($userInfo, JSON_UNESCAPED_UNICODE) . '<br />';
echo 'listen监听器输出:' . json_encode($event->setLoginCount(), JSON_UNESCAPED_UNICODE) . '<br />';
}
}
在控制器中执行
namespace app\controller;
use think\facade\Event;
use app\model\User;
class Index
{
public function index()
{
//……在此之前一系列的登录操作
$user = new User();
$userInfo = $user->getUserInfo();
echo '控制器输出:' . json_encode($userInfo, JSON_UNESCAPED_UNICODE) . '<br />';
Event::listen('UserLogin', 'app\listener\User');
Event::trigger('UserLogin');
}
}
输出结果
控制器输出:{"id":1,"username":"路人甲","login_count":0}
listen监听器输出:{"id":1,"username":"路人甲","login_count":0}
listen监听器输出:{"id":1,"username":"路人甲","login_count":1}
可以看到用户登录+1已经被解耦了,相应的如果增加用户IP记录,给登录异常用户发送邮件都可以这样做。