Symfony EventDispatcher 實現中介者模式,讓任意模組在不修改核心代碼的前提下,通過監聽/訂閱事件擴展行為。HttpKernel、Security、Form、Workflow 等核心子系統均大量依賴它。
Symfony\Contracts\EventDispatcher\Event 僅含 stopPropagation()。[$obj, 'method']、實作 __invoke 的物件。EventDispatcher。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');
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) { /* 發送歡迎券 */ }
});
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'));
}
});
| 事件名 | 觸發時機 | 典型用途 |
|---|---|---|
| kernel.request | 請求進入,控制器解析前 | 認證、路由重寫、區域設定 |
| kernel.controller | 控制器呼叫前 | 參數注入、表單預處理 |
| kernel.view | 控制器返回非 Response 時 | 序列化、模板渲染 |
| kernel.response | Response 生成後,發送前 | 緩存頭、CORS、壓縮、CSRF Cookie |
| kernel.finish_request | Response 發送後 | 清理、記錄耗時 |
| kernel.terminate | 終止階段(fastcgi_finish_request 後) | 發送郵件、寫日誌、異步任務 |
| kernel.exception | 未捕獲異常 | 錯誤頁、API 統一格式、Sentry 上報 |
lowercase.dot.separated.verb,如 order.created、user.password_changed。EventSubscriber 替代分散的 addListener,便於維護與測試。