Laravel 事件系统:用领域事件与监听器解耦业务与异步通知

test12026-09-130 次阅读

问题背景

下单支付成功后,常常要同时做发通知、同步 ERP、记日志等好几件事。若把这些逻辑全堆在控制器里,代码会迅速膨胀且难以测试。Laravel 的事件系统把"发生了什么"(事件)和"发生之后做什么"(监听器)分离,天然支持异步与广播。

定义事件

// app/Events/OrderPaid.php
namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use App\Models\Order;

class OrderPaid
{
    use Dispatchable;

    public function __construct(public Order $order) {}
}

监听器

// app/Listeners/SendOrderNotification.php
namespace App\Listeners;

use App\Events\OrderPaid;
use App\Notifications\OrderPaidNotify;

class SendOrderNotification
{
    public function handle(OrderPaid $event): void
    {
        $event->order->user->notify(new OrderPaidNotify($event->order));
    }
}

注册监听

// app/Providers/EventServiceProvider.php
protected $listen = [
    OrderPaid::class => [
        SendOrderNotification::class,
        \App\Listeners\SyncToErp::class,
    ],
];

触发与异步

// 在支付回调里
use App\Events\OrderPaid;

OrderPaid::dispatch($order);

// 让监听器异步执行:实现 ShouldQueue
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;

class SyncToErp implements ShouldQueue
{
    public function handle(OrderPaid $event): void
    {
        // 推送到 ERP,失败自动进队列重试
    }
}

要点

  • 事件名用"过去式"(OrderPaid)表达已发生的事实,语义清晰。
  • 实现 ShouldQueue 的监听器会自动进 Laravel 队列,失败可重试,不阻塞主流程。
  • 需要实时推前端时,让事件实现 ShouldBroadcast,监听器之外的客户端也能收到。
  • 事件越细粒度越好,监听器可独立增删,业务改动不影响触发方。
T

test1

文章作者

问题背景 下单支付成功后,常常要同时做发通知、同步 ERP、记日志等好几件事。若把这些逻辑全堆在控制器里,代码会迅速膨...

分类
技术
发布时间
2026-09-13
字数
约 1324 字
阅读
0 次