thinkphp笔记-事件
事件
事件和中间件有一点相似,只不过事件更加的精准定位更细腻的业务场景,也类似于前面提到的“服务”,可以初始化一些类。
事件可定义:事件类、(常用:)事件监听类、事件订阅类;
下面是一个简单的监听器示例:
<?php
namespace app\controller;
use think\facade\Event;
class TestEvent
{
public function __construct()
{
// 监听器 动态
// 第一个参数监听器的名称
Event::listen('TestListen', function($param) {
echo '监听器被触发' . $param;
});
}
public function info()
{
echo '登陆前准备';
// 触发监听器
// 参数一:对应的标识名 参数二:传递过去的参数
Event::trigger('TestListen', 'ok');
}
}
当访问http://localhost/xuexi/tp6/public/testevent/info的时候,会自动执行实例化。
也可是使用助手函数使用监听器,与Event::trigger一致
event('TestListen', 'ok');
我们也可以使用监听类来设计监听器,使用命令行创建;
php think make:listener TestListen
在listener文件夹下建一个Testlisten.php文件,成功后会在app下找到新建的listener文件夹和TestListen.php文件。
<?php
declare (strict_types = 1);
namespace app\listener;
class TestListen
{
/**
* 事件监听处理
*
* @return mixed
*/
public function handle($event)
{
//
}
}
将其稍微改造下,在handle中添加一个方法(触发监听的时候,所有要执行的代码都写在handle中)
<?php
declare (strict_types = 1);
namespace app\listener;
class TestListen
{
/**
* 事件监听处理
*
* @return mixed
*/
public function handle($event)
{
echo '监听器被触发' . $event;
}
}
然后在控制器中调用这个事件类的handle方法
<?php
namespace app\controller;
use app\listener\TestListen;
use think\facade\Event;
class TestEvent
{
public function __construct()
{}
public function info()
{
echo '登陆前准备';
Event::listen('TestListen', TestListen::class);
event('TestListen', 'ok');
}
}
在使用助手函数之前,需要先进行注册一下:Event::listen('TestListen', TestListen::class);,调用事件类。
当然还可以不用在代码中先注册,在app/event.php中进行统一的注册,之后仅仅在需要的地方event()使用即可。
首先在app/event.php文件中,添加监听类
<?php
// 事件定义文件
return [
// 事件类
'bind' => [
],
// 监听类
'listen' => [
'AppInit' => [],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
// 添加要监听的类
'TestListen' => [
\app\listener\TestListen::class
]
],
// 订阅类
'subscribe' => [
],
]
添加之后,在需要的控制器中,只需要一句话就OK。
public function info()
{
echo '登陆前准备';
event('TestListen', 'ok');
}
系统还内置了系统触发的事件,只要满足条件就会自动触发;
事件 | 描述 | 参数 |
---|---|---|
Appinit | 应用初始化时候触发 | 无 |
HttpRun | 应用开始时触发 | 无 |
HttpEnd | 应用结束时触发 | 当前响应对象实例 |
LogWrite | 日志write方法写入时候触发 | 当前写入的日志信息 |
RouteLoaded | 路由加载完成触发 | 无 |
我个人感觉这个监听器就类似于vue的钩子函数
比如,我要在Appinit时候,触发一个方法,可以在app/event.php中这样设置
// 监听类
'listen' => [
'AppInit' => [ \app\listener\TestListen::class ],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
'TestListen' => [
\app\listener\TestListen::class
]
],
事件监听类,可以同时监听多个监听类,只要绑定到一个标识符即可;
'TestListen' => [
\app\listener\TestOne::class,
\app\listener\TestListen::class,
\app\listener\TestTwo::class
]
然后在app/listener/TestOne.php、TestTwo.php两个文件
当在控制器中执行event(’TestListen‘)的时候,会自动执行TestListen中注册的三个事件类中的handle里面的代码。
监听类,最好是一对一,不要一对多,不方便后续的拆分和管理。
对于需要多个监听,监听类不够灵活,而且类会创建很多,可以使用订阅类;
订阅类就是将监听事件作为内部的方法用on+方法名来实现;
php think make:subscribe UserSub
之后会在app\subscribe下创建UserSub.php,文件中原始内容如下:
<?php
declare (strict_types = 1);
namespace app\subscribe;
class UserSub
{
}
添加一些内容订阅类就是将与某个功能有关的所有方法都放在一个类中,这样就不用在监听类中一个个的注册、引用了。
<?php
declare (strict_types = 1);
namespace app\subscribe;
// 订阅类就是将与User有关的所有方法都放在一个类中
class UserSub
{
public function onUserLogin()
{
echo '登录监听';
}
public function onUserLogout()
{
echo '退出监听';
}
}
在app/event.php中进行注册
// 订阅类
'subscribe' => [
'UserSub' => \app\subscribe\UserSub::class
],
或者直接去掉键也行
// 订阅类
'subscribe' => [
\app\subscribe\UserSub::class
],
在控制器中
public function login()
{
echo '登录成功';
// 直接使用UserSub里面的方法即可
// 可以理解为UserSub里面的没个方法都是一个监听器标签
event('UserLogin');
}
public function logout()
{
echo '退出成功';
event('UserLogout');
}
或者使用
Event::trigger('UserLogin');
对于事件类,很少有场景需要使用它,毕竟系统提供的各种精确方案较多;
php think make:event UserEvent
仅作了解
class UserEvent
{
public function __construct()
{
echo '我是事件类!';
}
}
Event::trigger(new UserEvent());