本文目录导读:

在ThinkPHP 6/8中,事件与监听器的绑定主要有以下几种方式,我会详细讲解并给出代码示例:
事件定义文件方式(推荐)
创建事件定义文件
在 app 目录下的 event.php 文件中定义:
<?php
// app/event.php
return [
// 事件绑定
'bind' => [
'UserLogin' => 'app\event\UserLogin',
'OrderCreate' => 'app\event\OrderCreate',
],
// 事件监听
'listen' => [
'app\event\UserLogin' => [
'app\listener\UserLoginListener',
'app\listener\UserLoginLog',
],
'app\event\OrderCreate' => [
'app\listener\OrderCreateListener',
'app\listener\SendSms',
'app\listener\SendEmail',
],
],
// 事件订阅
'subscribe' => [
'app\subscribe\UserSubscribe',
'app\subscribe\OrderSubscribe',
],
];
创建事件类
<?php
// app/event/UserLogin.php
namespace app\event;
class UserLogin
{
// 用户信息
public $user;
// 登录时间
public $loginTime;
// 登录IP
public $ip;
public function __construct($user, $loginTime, $ip)
{
$this->user = $user;
$this->loginTime = $loginTime;
$this->ip = $ip;
}
}
<?php
// app/event/OrderCreate.php
namespace app\event;
class OrderCreate
{
public $orderId;
public $orderData;
public function __construct($orderId, $orderData = [])
{
$this->orderId = $orderId;
$this->orderData = $orderData;
}
}
创建监听器
<?php
// app/listener/UserLoginListener.php
namespace app\listener;
use app\event\UserLogin;
class UserLoginListener
{
/**
* 事件监听处理
* @param UserLogin $event 事件对象
*/
public function handle(UserLogin $event)
{
// 更新用户最后登录时间
$user = $event->user;
$user->last_login_time = $event->loginTime;
$user->last_login_ip = $event->ip;
$user->save();
// 记录日志
trace("用户 {$user->username} 在 {$event->loginTime} 登录成功");
}
}
<?php
// app/listener/UserLoginLog.php
namespace app\listener;
use app\event\UserLogin;
class UserLoginLog
{
public function handle(UserLogin $event)
{
$data = [
'user_id' => $event->user->id,
'login_time' => $event->loginTime,
'ip' => $event->ip,
'agent' => request()->header('user-agent')
];
// 写入登录日志表
Db::name('login_log')->insert($data);
}
}
监听器优先级配置
<?php
// app/listener/UserLoginListener.php
namespace app\listener;
use app\event\UserLogin;
class UserLoginListener
{
/**
* 监听器优先级(数值越大优先级越高)
*/
public $priority = 10;
public function handle(UserLogin $event)
{
// 处理逻辑
}
}
创建订阅器
<?php
// app/subscribe/UserSubscribe.php
namespace app\subscribe;
use think\Event;
class UserSubscribe
{
public function onUserLogin($event)
{
// 处理用户登录事件
echo '用户登录了';
}
public function onUserLogout($event)
{
// 处理用户退出事件
echo '用户退出了';
}
/**
* 注册订阅者
*/
public function subscribe(Event $event)
{
$event->listen('UserLogin', [$this, 'onUserLogin']);
$event->listen('UserLogout', [$this, 'onUserLogout']);
}
}
动态绑定事件监听器
<?php
namespace app\controller;
use think\facade\Event;
class User
{
public function login()
{
// ...登录逻辑...
// 方式1:动态绑定事件监听器
Event::listen('UserLogin', function ($event) {
// 即时监听
echo $event->user->username . ' 登录了';
});
// 方式2:动态绑定多个监听器
Event::listen('UserLogin', [
'app\listener\SendWelcomeEmail',
function ($event) {
// 匿名函数监听
}
]);
// 方式3:绑定事件类
Event::listen('app\event\UserLogin', 'app\listener\UserLoginListener');
// 触发事件
$event = new UserLogin($user, time(), request()->ip());
Event::trigger('UserLogin', $event);
}
}
在控制器中使用事件
<?php
namespace app\controller;
use think\facade\Event;
use app\event\UserLogin;
use app\event\OrderCreate;
use app\model\User;
use app\model\Order;
class Test
{
// 触发用户登录事件
public function login()
{
$user = User::find(1);
// 创建事件并触发
$event = new UserLogin($user, date('Y-m-d H:i:s'), request()->ip());
Event::trigger($event); // 多态形式触发
return '登录成功';
}
// 触发订单创建事件
public function createOrder()
{
$orderId = 10086;
$orderData = [
'user_id' => 1,
'amount' => 999.00,
'status' => 'pending'
];
// 触发事件
Event::trigger('OrderCreate', $orderData); // 简单形式
// 或
Event::trigger(new OrderCreate($orderId, $orderData)); // 多态形式
return '订单创建成功';
}
// 异步事件处理
public function asyncEvent()
{
// 使用异步事件
Event::async('UserLogin', ['user_id' => 1], 3600); // 延迟1小时执行
}
// 批量触发事件
public function batchEvent()
{
$events = [
['UserLogin', ['user_id' => 1]],
['OrderCreate', ['order_id' => 10086]],
];
Event::triggerBatch($events); // 批量触发
}
}
命令行模式绑定
<?php
// config/event.php
return [
// 命令行模式定义
'command' => [
'UserLogin' => ['app\listener\UserLoginListener'],
'OrderCreate' => ['app\listener\OrderCreateListener'],
],
];
事件监听器的完整示例
<?php
// app/listener/OrderCreateListener.php
namespace app\listener;
use app\event\OrderCreate;
use think\facade\Log;
use think\facade\Cache;
class OrderCreateListener
{
/**
* 监听器优先级
*/
public $priority = 5;
/**
* 处理事件
*/
public function handle(OrderCreate $event)
{
// 缓存订单数据
Cache::set("order_{$event->orderId}", $event->orderData, 3600);
// 清空用户订单缓存
Cache::delete("user_orders_{$event->orderData['user_id']}");
// 记录日志
Log::info("订单创建:{$event->orderId}");
// 其他业务逻辑,如发送邮件、通知等
$this->sendNotification($event);
}
private function sendNotification($event)
{
// 发送通知逻辑
}
/**
* 事件错误处理
*/
public function failed(OrderCreate $event, \Throwable $e)
{
Log::error("订单事件处理失败:{$e->getMessage()}");
}
}
基于注解的自动绑定(ThinkPHP 8)
<?php
// app/controller/User.php
namespace app\controller;
use think\annotation\route\Group;
use think\annotation\route\Route;
use think\facade\Event;
#[Group('user')]
class User
{
#[Route('POST', 'login')]
public function login()
{
// 登录逻辑
$user = User::find(1);
// 触发事件
Event::trigger('UserLogin', $user);
return json(['code' => 0, 'msg' => '登录成功']);
}
}
最佳实践建议
- 事件命名规范:使用语义化的名称,如
UserLogin、OrderCreate等 - 业务解耦:事件主要用于业务解耦,避免类与类之间的直接依赖
- 异步处理:对于耗时操作(如发邮件、通知等),考虑使用异步事件或队列
- 错误处理:在监听器中做好异常处理,避免影响主业务流程
- 性能考虑:合理使用事件,避免过度设计导致性能问题
通过以上方式,你可以灵活地在ThinkPHP项目中绑定事件和监听器,实现业务逻辑的解耦和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播