ThinkPHP 8事件系统实战:通过事件监听器解耦订单通知逻辑

2026-08-15 0 149

很多人在一个控制器里写完了所有业务,比如下单之后要发短信、写日志、更新库存、赠送积分。一开始没啥,后来越加越多,一个方法几百行,稍微改动一个通知就感觉整个下单流程被动。前阵子我用ThinkPHP 8重写一个订单模块,用事件系统把“下单后的事”全部拆了出去,现在主流程干干净净。

事件是什么

事件就是“发生了一件事”。ThinkPHP的事件系统允许你在业务代码里“触发”一个事件,然后由监听器去响应。业务方不关心谁去响应,响应者也不用打扰主流程。这就是解耦

第一步:定义事件类

在ThinkPHP 8里,事件类就是普通的类,用来携带数据。我建了一个 appeventOrderCreated 事件类。

<?php
namespace appevent;

class OrderCreated
{
    public $order;
    public $user;

    public function __construct($order, $user)
    {
        $this->order = $order;
        $this->user = $user;
    }
}

构造函数接收订单数据和用户数据。谁触发事件,谁负责传参。

第二步:注册事件与监听器

ThinkPHP的事件可以通过 config/event.php 文件定义。我在 event 数组里加上事件和监听器的映射。

<?php
return [
    'bind' => [
        'OrderCreated' => 'appeventOrderCreated',
    ],
    'listen' => [
        'appeventOrderCreated' => [
            'applistenerSendSmsListener',
            'applistenerWriteLogListener',
            'applistenerUpdateInventoryListener',
        ],
    ],
];

意思是当触发 appeventOrderCreated 事件时,依次执行这三个监听器。

第三步:编写监听器

监听器需要实现 handle 方法。比如发送短信的监听器:

<?php
namespace applistener;

class SendSmsListener
{
    public function handle($event)
    {
        // 调用短信服务,使用事件中携带的数据
        $orderNo = $event->order['order_no'];
        $phone = $event->user['mobile'];
        // 假装发了一条短信
        // SmsService::send($phone, "您的订单 {$orderNo} 已确认");
        trace("发送短信给 {$phone},订单号:{$orderNo}");
    }
}

日志监听器、库存监听器同理。每个监听器只管自己那一摊事。

第四步:在业务中触发事件

下订单的控制器方法变得非常简单:

<?php
namespace appcontroller;

use thinkfacadeEvent;
use appeventOrderCreated;

class Order
{
    public function create()
    {
        // 创建订单主记录
        $order = ...;
        // 如果有其他必要操作,写在这里
        // 触发订单创建完成事件
        Event::trigger(new OrderCreated($order, $user));

        return json(['code' => 1, 'msg' => '下单成功']);
    }
}

如果你后续要加一个“下单后给渠道商返佣”,不用改控制器,只需要新建一个监听器,然后在 event.php 里注册进去即可。

第五步:异步监听(队列)

短信和日志其实不一定要同步执行。ThinkPHP事件支持将监听器设置为异步,借助消息队列。我当初把发短信的监听器丢到了队列里,接口秒回。

首先在 event.php 里设置监听器为队列模式:

'listen' => [
    'appeventOrderCreated' => [
        'applistenerSendSmsListener' => 'queue',
        'applistenerWriteLogListener',
        ...
    ],
],

然后监听器的 handle 方法需要返回一个队列任务或者使用ShouldQueue? 不过ThinkPHP 8里通常通过thinkqueueListener来消费。这个看业务情况,如果是核心依赖的话建议同步,非核心异步。

踩坑记录

1. 事件类被 Event::trigger 触发时,监听器的 handle 参数是事件对象,不是事件名。

2. 在event.php中注册监听器时,一定要用完整命名空间,别用短别名,否则系统找不到。

3. 如果你在监听器里修改了 $event 属性的值,其实不会影响回传,因为事件对象是引用传递,但如果你重新赋值了监听器里的 $event,不会影响到外部。更多时候我们需要在主流程里获取结果,可以用Event::until获取第一个非null的返回。

更进一步:事件监听还可以用注解注册

如果你不喜欢配置文件,想直接用属性注解(PHP8)注册监听器,ThinkPHP 8也支持。比如在监听器类上写#[Listen('appeventOrderCreated')],然后通过命令行扫描生成事件。个人还是喜欢事件文件集中管理,容易找。

总结

事件系统不是复杂概念,就是“多了一个回调列表”。用了它之后,我的下单方法保留了核心逻辑,所有扩展功能都扔给了监听器。代码好读多了,也好测试了。下次添加新功能,真的就是加一个监听器的事。

ThinkPHP 8事件系统实战:通过事件监听器解耦订单通知逻辑
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

版权声明:
本站资源有的来自互联网收集整理,本站纯免费分享提供学习使用,如果侵犯了您的合法权益,请联系本站我们会及时删除。
本站资源仅供研究、学习交流之用,免费开源项目不代表完全可商用,若商业用途请先咨询开发企业能否商用,否则产生的一切后果将由下载用户自行承担。
原创板块未经允许不得转载,否则将追究法律责任。

淘吗网 thinkphp ThinkPHP 8事件系统实战:通过事件监听器解耦订单通知逻辑 https://www.taomawang.com/server/thinkphp/2547.html

下一篇:

已经没有下一篇了!

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务