Skip to main content

事件是什麼

Laravel 的事件系統是簡潔的觀察者模式實作。 你可以透過在應用程式中發生「事件」時觸發,並定義能對其做出反應的監聽器,將元件之間的相依性降到最低。 例如,發起「訂單成立」事件後,「發送確認信」、「扣減庫存」、「通知 Slack」等多個監聽器都能各自獨立地執行。 訂單處理程式碼完全不需要知道 email 或 Slack 通知的實作細節。
事件類別存放於 app/Events,監聽器類別存放於 app/Listeners。 若不存在則 Artisan 指令會自動建立。

建立事件與監聽器

make:eventmake:listener Artisan 指令產生類別骨架。
不帶參數執行時會進入互動模式。

註冊事件

事件自動探索

預設情況下,Laravel 會掃描 app/Listeners 目錄自動註冊監聽器。 它會依 handle__invoke 方法的引數型別推論與事件的對應。
透過 PHP 的聯合型別,可讓單一方法接收多種事件。
若把監聽器放在其他目錄,可於 bootstrap/app.php 指定額外掃描位置。
也可用 wildcard 指定多個目錄。
要確認已註冊的監聽器可執行下列指令。
在正式環境快取監聽器 manifest 可提升效能。 部署時可執行 php artisan optimizephp artisan event:cache。 要清除快取則使用 php artisan event:clear

手動註冊

也可以在 AppServiceProviderboot 方法透過 Event Facade 手動註冊。
也可以透過閉包註冊。

定義事件

事件類別是資料的容器。它不含邏輯,只以屬性儲存與事件相關的資訊。
透過 SerializesModels trait,可在佇列化的監聽器序列化事件時正確處理 Eloquent 模型。

觸發事件

透過 dispatch 靜態方法或 event() 輔助函式觸發事件。
也有依條件觸發的方法。

資料庫 Transaction 之後才觸發

若要在 transaction commit 之後才觸發事件,可在事件類別實作 ShouldDispatchAfterCommit 介面。 若 transaction 失敗則事件會被丟棄。

監聽器的實作

監聽器透過 handle 方法接收事件。 建構子中的相依會由服務容器自動注入。
若監聽器的 handle 方法回傳 false,可以中斷事件傳遞到後續監聽器。

佇列化的監聽器

寄信或 HTTP 請求等耗時處理,可作為佇列化的監聽器非同步執行。 只需實作 ShouldQueue 介面,事件觸發時監聽器就會自動進入佇列。
使用佇列化的監聽器前,需先設定佇列並啟動 worker。 詳情請見佇列與工作頁面。

自訂佇列連線 / 名稱 / 延遲

可用 PHP 屬性設定連線、佇列名稱與延遲時間。
也可以用方法動態決定值。

最大重試次數與逾時

使用 #[Tries]#[Timeout] 屬性控制失敗時的行為。

失敗時的處理

定義 failed 方法可以描述監聽器超過重試次數後失敗的後續處理。

事件訂閱者

透過事件訂閱者,可以將多個相關事件處理程式集中在同一個類別。

建立訂閱者

subscribe 方法回傳事件與 handler 的對應陣列。

註冊訂閱者

若事件自動探索啟用,subscribe 方法回傳陣列的訂閱者會自動註冊。 若要手動註冊,可在 AppServiceProviderboot 方法呼叫 Event::subscribe

實戰範例:使用者註冊時寄送歡迎信

1

建立事件類別

編輯 app/Events/UserRegistered.php,加入用來保存註冊使用者的屬性。
2

建立監聽器類別

為了讓寄信非同步進行,實作 ShouldQueue
3

在控制器中觸發事件

在使用者註冊處理後呼叫 UserRegistered::dispatch()
RegisterController 只需要觸發 UserRegistered 事件,不需要知道寄信的實作。 未來如果加入「註冊時也通知 Slack」的需求,也完全不必修改控制器。
4

啟動 worker

要處理佇列化的監聽器,請啟動 worker。
在事件自動探索啟用時,不需要在 AppServiceProvider 手動註冊。 放在 app/Listeners 目錄的監聽器會被自動偵測。
執行 php artisan event:list 可以查看已註冊的事件與監聽器清單。 請定期檢查是否有意料外的監聽器。
最後修改於 2026年8月2日