理論突破,往往產生實踐的創新。反之實踐不甚其解,通常是沒有掌握好理論。
Symfony
事件系統,涉及到派遣器(事件觸發),訂閱器(事件收集),事件物件(資料附加),監聽器(事件執行),事件傳播,事件佇列優先順序,以及程式元件間的通訊
服務容器
每一個服務都被存放於一個特殊的名為
service container
(服務容器)之中 容器把物件的組織方式中心化
- 取得並使用服務
- 在控制器中藉助“服務的類名或介面名”, 對
action
的引數進行type-hinting
以“請求”容器中的服務 - 可以使用唯一的 "Service ID" 來直接訪問服務, 繼承 Controller 類時內部可直接從容器中取出服務
- 在控制器中藉助“服務的類名或介面名”, 對
事件派遣
Symfony
自身提供的內部事件,被定義在KernelEvents
類中 在sf
程式執行期間,大量的事件通知會被觸發,程式可監聽這些通知,並執行任意程式碼作為響應
- 事件監聽器
- 通常由事件類和監聽介面組成
- 接收事件物件引數,事件物件持有派遣器自身引用,該引用例項可決定事件能否繼續傳播
- 事件監聽器優先順序,Symfony的內部監聽,其優先順序範圍是-255到255,預設值為0,順序執行
- 監聽器模式
- 監聽者模式是基於:註冊-回撥的事件/訊息通知處理模式,就是被監控者將訊息通知給所有監控者
- 事件派遣器
- 事件觸發呼叫者,事件源
- 事件類註冊成服務,可命名
tags
- 一個單一的事件派遣器建立之後,它要維護全部相關監聽器的“登記”
- 當事件通過
dispatcher
被派遣時,所有已註冊的監聽器會接到通知 - 核心通知
dispatcher
物件派遣事件,派遣器通知事件的全部監聽器,監聽器執行
- 事件訂閱
- 訂閱器始終明確知道正在監聽的事件
- 定義了一個或多個方法,用於監聽一個或多個事件
- 監聽 VS 訂閱
- 訂閱器易於複用 與事件有關的內容存在於類中,而不是存在於服務定義中,故
sf
內部使用訂閱器 - 監聽器更靈活,因
bundles
可以有條件地開啟或關閉它們,基於配置檔案中的某些“選項值”
- 訂閱器易於複用 與事件有關的內容存在於類中,而不是存在於服務定義中,故
EventDispatcher元件
- 作用 使元件之間“通過派遣事件和監聽事件”進行互相通訊
- 應用背景
- 需要在專案中提供一個外掛系統
EventDispatcher
元件以一種簡單高效的方式,實現了Mediator
設計模式- 中介者定義一個介面用於與各同事物件通訊
- 每一個同事物件在需與其他同事通訊時,與它的中介者通訊
- 使控制集中化,減少了子類的生成,將各個同事類解耦,協議多向
- 可以使用
Observer
模式與Mediator
通訊
- 事件
- 當一個事件被派遣時,該事件被多個監聽器來監聽。
- 一個Event例項將被同時建立,並被傳遞給所有的監聽器
Event
物件自身往往包含著被派遣事件的資料
- 事件名稱和事件物件
Event
類 預設包含一個用於停止event.propagation
方法- 特定事件的資料,則為一個擁有附加方法來取得或重寫這些資料的特殊子類
- 連線到監聽器
- 欲利用已有的事件,需要訪問派遣器下的監聽器
- 派遣器的
addListener()
方法被呼叫時,可以把任何一個有效的PHP回撥(callable)關聯到那個事件- 同
yii2
一樣, 監聽器addListener()方法有三個引數 - 事件名稱(字串),監聽器需要監聽到它
- 一個PHP回撥,將在特定的事件被派遣時被執行
- 一個可選的整數優先順序(愈高則愈重要,該監聽將被愈早地觸發)
- 同
- 一旦監聽被註冊到派遣器,它就等待著事件被通知(到自己)
- 在服務容器中註冊事件監聽
- 支援把事件派遣器註冊成服務
- 支援把監聽器註冊成服務
- 支援把訂閱器註冊成服務
- 派遣Event
dispatch()
方法可以通知給定事件的全部監聽- 要派遣的事件名稱,以及用於傳給每個監聽的Event例項
- 事件派遣器永遠返回被派遣的事件物件
- 使用事件訂閱器
- 監聽事件的常規方式就是去註冊一個監聽器給事件派遣器
- 或通過
event subscriber
(訂閱器), 向派遣器精確通報它要訂閱哪些事件- 除了它自己告訴派遣器“要監聽哪些事件”之外,也需要將該訂閱器註冊給派遣器
- 停止Event Flow/Propagation
- 原因 在某些場合,一個監聽在作動時,防止其他監聽被呼叫是有意義
- 換言之,監聽器必須能夠告訴派遣器,停止向後續的監聽進行關於此事件的全部傳播
EventDispatcher Aware
的事件和監聽EventDispatcher
始終向監聽器傳遞被派遣的事件、事件名和一個對派遣器自身的引用
- 原因 在某些場合,一個監聽在作動時,防止其他監聽被呼叫是有意義
- 其他派遣器
The Container Aware Event Dispatcher
The Immutable Event Dispatcher
The Traceable Event Dispatcher(由HttpKernel元件提供)