ThinkPHP项目订阅者与事件组

wen PHP项目 3

本文目录导读:

ThinkPHP项目订阅者与事件组

  1. 基础概念
  2. 事件订阅者(Event Subscriber)
  3. 事件组(Event Groups)
  4. 实际应用示例
  5. 事件触发
  6. 注册订阅者
  7. 高级用法

在ThinkPHP框架中,事件订阅者和事件组是事件系统的重要组成部分,让我详细介绍它们的用法:

基础概念

事件(Event)

// 创建事件类
namespace app\event;
class UserLogin
{
    public $user;
    public function __construct($user)
    {
        $this->user = $user;
    }
}

监听器(Listener)

// 创建监听器
namespace app\listener;
class SendLoginNotify
{
    public function handle(UserLogin $event)
    {
        // 处理登录通知
        echo "用户 {$event->user->name} 登录成功";
    }
}

事件订阅者(Event Subscriber)

事件订阅者允许在一个类中监听多个事件:

namespace app\subscriber;
class UserSubscriber
{
    /**
     * 定义订阅的事件
     * @return array
     */
    public function subscribe()
    {
        return [
            'UserLogin' => 'onUserLogin',
            'UserLogout' => 'onUserLogout',
            'UserRegister' => ['onUserRegister', 'onUserRegisterSubscribe'],
        ];
    }
    // 处理用户登录
    public function onUserLogin($event)
    {
        // 记录登录日志
        Log::info('用户登录: ' . $event->user->name);
    }
    // 处理用户退出
    public function onUserLogout($event)
    {
        // 清除会话等操作
        Cache::delete('user_' . $event->user->id);
    }
    // 处理用户注册
    public function onUserRegister($event)
    {
        // 发送欢迎邮件
    }
    // 注册后的额外操作
    public function onUserRegisterSubscribe($event)
    {
        // 订阅默认服务
    }
}

事件组(Event Groups)

事件组是多个相关事件的集合,便于管理和监听:

// 定义事件组配置
// config/event.php
return [
    'bind' => [
        'AppInit' => 'app\event\AppInit',
        'HttpRun' => 'app\event\HttpRun',
        'HttpEnd' => 'app\event\HttpEnd',
        'UserLogin' => 'app\event\UserLogin',
        'UserLogout' => 'app\event\UserLogout',
    ],
    'listen' => [
        'AppInit' => [],
        'HttpRun' => [],
        'HttpEnd' => [],
        'UserLogin' => [
            'app\listener\SendLoginNotify',
            'app\listener\RecordLoginHistory',
        ],
        'UserLogout' => [
            'app\listener\ClearUserCache',
        ],
    ],
    'subscribe' => [
        'app\subscriber\UserSubscriber',
        'app\subscriber\OrderSubscriber',
    ],
];

实际应用示例

订单事件组示例

// 创建订单事件组
namespace app\event\group;
class OrderEvent
{
    // 订单创建
    public function onOrderCreate($order)
    {
        // 记录订单日志
        Log::info("订单创建成功: " . $order->order_no);
    }
    // 订单支付
    public function onOrderPay($order)
    {
        // 更新订单状态
        $order->status = 1;
        $order->save();
        // 发送支付成功通知
        event('SendMessage', $order);
    }
    // 订单取消
    public function onOrderCancel($order)
    {
        // 恢复库存
        // 记录日志
        Log::info("订单取消: " . $order->order_no);
    }
    // 订单完成
    public function onOrderComplete($order)
    {
        // 发送评价提醒
        // 更新用户积分
    }
}

多模块事件订阅

namespace app\common\subscriber;
class SystemSubscriber
{
    public function subscribe()
    {
        return [
            'AppInit' => ['onAppInit', 'checkSystemStatus'],
            'HttpEnd' => 'onHttpEnd',
            'LogWrite' => 'onLogWrite',
        ];
    }
    public function onAppInit()
    {
        // 系统初始化检查
        $this->checkSystemStatus();
    }
    public function checkSystemStatus()
    {
        // 检查系统运行状态
        if (config('app.debug') === false) {
            // 生产环境检查逻辑
        }
    }
    public function onHttpEnd()
    {
        // 记录请求耗时
        $time = microtime(true) - THINK_START;
        Log::info('请求耗时: ' . $time . 's');
    }
    public function onLogWrite()
    {
        // 日志写入后的操作
    }
}

事件触发

// 在控制器或服务中触发事件
class UserController extends BaseController
{
    public function login()
    {
        $user = User::find($id);
        // 触发用户登录事件
        event('UserLogin', $user);
        // 或使用事件类
        event(new UserLogin($user));
        // 触发事件组
        event('OrderEvent', $order, 'onOrderCreate');
    }
}

注册订阅者

// 方式1:配置文件
// config/event.php
'subscribe' => [
    'app\subscriber\UserSubscriber',
    'app\common\subscriber\SystemSubscriber',
],
// 方式2:动态注册(在服务提供者中)
// app/provider/EventService.php
use think\facade\Event;
class EventService extends Service
{
    public function boot()
    {
        Event::subscribe('app\subscriber\UserSubscriber');
        Event::subscribe('app\common\subscriber\SystemSubscriber');
    }
}

高级用法

事件优先级

// 支持监听器优先级(数值越大越先执行)
'listen' => [
    'UserLogin' => [
        [ 'app\listener\RecordLoginHistory', 10 ],
        [ 'app\listener\SendLoginNotify', 5 ],
    ],
],

条件监听

// 带条件的监听器
class OrderListener
{
    public function handle($event)
    {
        if ($event->amount > 1000) {
            // 大额订单特殊处理
            event('BigAmountOrder', $event);
        }
    }
}

通过合理使用事件订阅者和事件组,可以让你的代码更加模块化,降低耦合度,提高代码的可维护性。

抱歉,评论功能暂时关闭!