首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Symfony EventDispatcher 組件深度解析:事件驅動架構實戰

     編輯:PHP 相關知識

EventDispatcher:解耦擴展點的核心組件

Symfony EventDispatcher 實現中介者模式,讓任意模組在不修改核心代碼的前提下,通過監聽/訂閱事件擴展行為。HttpKernel、Security、Form、Workflow 等核心子系統均大量依賴它。

核心概念

  • Event(事件對象):攜帶上下文數據,傳遞給所有監聽器。基類 Symfony\Contracts\EventDispatcher\Event 僅含 stopPropagation()。
  • Listener(監聽器):可呼叫體,接收 Event 參數。可為 Closure、陣列 [$obj, 'method']、實作 __invoke 的物件。
  • Dispatcher(調度器):管理監聽器註冊、優先級、調度流程。核心類 EventDispatcher。
  • Subscriber(訂閱者):實作 EventSubscriberInterface,靜態方法 getSubscribedEvents() 返回 [eventName => [method, priority]],批次註冊更清晰。

基本使用流程

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;

$dispatcher = new EventDispatcher();

// 1. 註冊監聽器(含優先級,數值越大越早執行)
$dispatcher->addListener('order.created', function (Event $event) {
    // 發送確認郵件
}, 10); // 高優先級

$dispatcher->addListener('order.created', function (Event $event) {
    // 更新庫存
}, 0); // 預設優先級

// 2. 調度事件
$event = new OrderCreatedEvent($order);
$dispatcher->dispatch($event, 'order.created');

自定義 Event 傳遞業務數據

use Symfony\Contracts\EventDispatcher\Event;

class OrderCreatedEvent extends Event {
    public function __construct(
        public readonly Order $order,
        public readonly bool $isNewCustomer = false
    ) {}
}

// 監聽器中獲取
$dispatcher->addListener('order.created', function (OrderCreatedEvent $event) {
    $order = $event->order;
    if ($event->isNewCustomer) { /* 發送歡迎券 */ }
});

EventSubscriber 批次註冊(推薦)

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class OrderNotifier implements EventSubscriberInterface {
    public static function getSubscribedEvents(): array {
        return [
            'order.created' => [
                ['sendConfirmation', 10],
                ['notifyWarehouse', 5],
                ['logAnalytics', 0],
            ],
            'order.cancelled' => ['processRefund', 0],
        ];
    }
    public function sendConfirmation(OrderCreatedEvent $event) { /* ... */ }
    public function notifyWarehouse(OrderCreatedEvent $event) { /* ... */ }
    public function logAnalytics(OrderCreatedEvent $event) { /* ... */ }
    public function processRefund(OrderCancelledEvent $event) { /* ... */ }
}

// 註冊
$dispatcher->addSubscriber(new OrderNotifier());

停止事件傳播

$dispatcher->addListener('kernel.exception', function (ExceptionEvent $event) {
    if ($event->getThrowable() instanceof UserNotFoundException) {
        $event->stopPropagation(); // 後續監聽器不再執行
        $event->setResponse(new RedirectResponse('/login'));
    }
});

HttpKernel 核心事件(必知)

事件名觸發時機典型用途
kernel.request請求進入,控制器解析前認證、路由重寫、區域設定
kernel.controller控制器呼叫前參數注入、表單預處理
kernel.view控制器返回非 Response 時序列化、模板渲染
kernel.responseResponse 生成後,發送前緩存頭、CORS、壓縮、CSRF Cookie
kernel.finish_requestResponse 發送後清理、記錄耗時
kernel.terminate終止階段(fastcgi_finish_request 後)發送郵件、寫日誌、異步任務
kernel.exception未捕獲異常錯誤頁、API 統一格式、Sentry 上報

效能與最佳實踐

  • 優先級:系統內建監聽器通常在 -255 到 255 區間,業務代碼建議 0~100。
  • 避免在監聽器中做重 IO/阻塞操作,異步任務交給 Messenger/Queue。
  • 事件名命名規範:lowercase.dot.separated.verb,如 order.created、user.password_changed。
  • 使用 EventSubscriber 替代分散的 addListener,便於維護與測試。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved