在最新的6.0版本中引入了新的事件系统用以替代5.1版本的行为,同时也接管了数据库事件和模型事件。
本篇主要描述下新版的事件系统以及查询事件、模型事件的使用。
定义事件
事件系统的所有操作都通过thinkfacadeEvent类进行静态调用
事件系统使用了观察者模式,提供了解耦应用的更好方式。在你需要监听事件的位置,添加如下代码:
立即学习“PHP免费学习笔记(深入)”;
Event::trigger('UserLogin');
或者使用助手函数
event('UserLogin');
这里UserLogin表示一个事件标识,如果你定义了单独的事件类,你可以使用事件类名,甚至可以传入一个事件类实例。
event('appeventUserLogin');
事件类可以通过命令行快速生成
php think make:event UserLogin
默认会生成一个appeventUserLogin事件类,也可以指定完整类名生成。
我们可以给事件类添加方法
namespace appevent; use appmodelUser; class UserLogin { public $user; public function __construct(User $user) { $this->user = $user; } }
一般事件类无需继承任何其它类。
你可以给事件类绑定一个事件标识
Event::bind('UserLogin', 'appeventUserLogin');
或者在应用的event.php事件定义文件中批量绑定。
return [ 'bind' => [ 'UserLogin' => 'appeventUserLogin', // 更多事件绑定 ], ];
如果你没有定义事件类的话,则无需绑定。
ThinkPHP的事件系统不依赖事件类,如果没有额外的需求,仅通过事件标识也可以使用。
你可以在event方法中传入一个事件参数
event('UserLogin', $user);
事件监听
你可以手动注册一个事件监听
Event::listen('UserLogin', function($user) { // });
或者使用监听类
Event::listen('UserLogin', 'applistenerUserLogin');
可以通过命令行快速生成一个事件监听类
php think make:listener UserLogin
默认会生成一个applistenerUserLogin事件监听类,也可以指定完整类名生成。
事件监听类只需要定义一个handler方法,支持依赖注入。
<?php namespace applistener; class UserLogin { public function handle($user) { // 事件监听处理 } }
在handler方法中如果返回了false,则表示监听中止,将不再执行该事件后面的监听。
一般建议直接在事件定义文件中定义对应事件的监听。
return [ 'bind' => [ 'UserLogin' => 'appeventUserLogin', // 更多事件绑定 ], 'listen' => [ 'UserLogin' => ['applistenerUserLogin'], // 更多事件监听 ], ];
事件订阅
可以通过事件订阅机制,在一个监听器中监听多个事件,例如通过命令行生成一个事件订阅者类,
php think make:subscribe User
默认会生成appsubscribeUser类,或者你可以指定完整类名生成。
然后你可以在事件订阅类中添加不同事件的监听方法,例如:
<?php namespace appsubscribe; class User { public function onUserLogin($user) { // 事件响应处理 } public function onUserLogout($user) { // 事件响应处理 } }
监听事件的方法命名规范是on+事件标识(驼峰命名),然后注册该事件订阅
Event::subscribe('appsubscribeUser');
一般建议直接在事件定义文件中定义
return [ 'bind' => [ 'UserLogin' => 'appeventUserLogin', // 更多事件绑定 ], 'listen' => [ 'UserLogin' => ['applistenerUserLogin'], // 更多事件监听 ], 'subscribe' => [ 'appsubscribeUser', // 更多事件订阅 ], ];
内置事件
内置的系统事件包括:
AppInit事件定义必须在全局事件定义文件中定义,其它事件支持在应用的事件定义文件中定义。
原来5.1的一些行为标签已经废弃,所有取消的标签都可以使用中间件更好的替代。可以把中间件看成处理请求以及响应输出相关的特殊事件。事实上,中间件的handle方法只是具有特殊的参数以及返回值而已。
查询事件
数据库操作的回调也称为查询事件,是针对数据库的CURD操作而设计的回调方法,主要包括:
使用下面的方法注册数据库查询事件
thinkfacadeDb::event('before_select', function ($query) { // 事件处理 return $result; });
同一个查询事件可以注册多个响应执行。查询事件在新版里面也已经被事件系统接管了,因此如果你注册了一个before_select查询事件监听,底层其实是向标识为db.before_select的事件注册了一个监听。
查询事件的方法参数只有一个:当前的查询对象。但你可以通过依赖注入的方式添加额外的参数。
模型事件
模型事件是指在进行模型的查询和写入操作的时候触发的操作行为。
模型事件只在调用模型的方法生效,使用查询构造器操作是无效的。
模型支持如下事件:
注册的回调方法支持传入一个参数(当前的模型对象实例),但支持依赖注入的方式增加额外参数。
如果before_write、before_insert、 before_update 、before_delete事件方法中返回false或者抛出thinkexception
ModelEventException异常的话,则不会继续执行后续的操作。
模型事件定义
最简单的方式是在模型类里面定义静态方法来定义模型的相关事件响应。
<?php namespace appindexmodel; use thinkModel; use appindexmodelProfile; class User extends Model { public static function onBeforeUpdate($user) { if ('thinkphp' == $user->name) { return false; } } public static function onAfterDelete($user) { Profile::destroy($user->id); } }
参数是当前的模型对象实例,支持使用依赖注入传入更多的参数。
模型事件观察者
如果希望模型的事件单独管理,可以给模型注册一个事件观察者,例如:
<?php namespace appindexmodel; use thinkModel; class User extends Model { protected $observerClass = 'appindexobserverUser'; }
User观察者类定义如下:
<?php namespace appindexobserver; use appindexmodelProfile; class User { public function onBeforeUpdate($user) { if ('thinkphp' == $user->name) { return false; } } public function onAfterDelete($user) { Profile::destroy($user->id); } }
观察者类的事件响应方法的第一个参数就是模型对象实例,你依然可以通过依赖注入传入其它的对象参数。
PHP中文网,大量的免费ThinkPHP入门教程,欢迎在线学习!
本文转自:https://blog.thinkphp.cn/1037387