摘要:事件代碼事件名,事件的唯一標識在監聽器里要操作的對象在監聽器里要操作的對象繼承在訂閱器的業務邏輯上,需要使用和對象,所以本事件包含這兩個類的對象。
大家好,這篇文章將通過我在實際開發工作中的例子,來介紹Symfony的EventDispatcher組件的使用及實現原理。
這個組件在實際開發過程中非常的有用,它能夠使代碼的業務邏輯變的非常清晰,增加代碼的復用性,代碼的耦合性也大大降低。
簡介具體的介紹大家可以查看官方的文檔,下面是文檔地址。
文檔地址
組成一個 dispatcher 對象,保存了事件名稱和其對應監聽器
一個 event,有一個全局唯一的事件名稱。包含一些在訂閱器里需要訪問的對象。
使用示例# 初始時,添加監聽器 $dispatcher = new EventDispatcher(); $disptacher->addSubscriber(new BIReportSubscriber()); // BI上報功能 $disptacher->addSubscriber(new MediaPlayerSubscriber()); // 維護播放器信息統一
SymfonyComponentEventDispatcherEventDispatcher
class BIReportSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents () { // 監聽的不同事件,當事件觸發時,會調用 onResponse 方法 return [ MusicResponseEvent::NAME => "onResponse", ChildrenResponseEvent::NAME => "onResponse", FmResponseEvent::NAME => "onResponse", NewsResponseEvent::NAME => "onResponse", ]; } public function onResponse(AResponseEvent $event) { /* * 一些具體的業務邏輯 * 進行 BI 上報 */ }
class MediaPlayerSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents () { return [ MusicResponseEvent::NAME => "onResponse", FmResponseEvent::NAME => "onResponse", ChildrenResponseEvent::NAME => "onResponse", NewsResponseEvent::NAME => "onResponse", ]; } public function onResponse(AResponseEvent $event) { /* * 一些具體的業務邏輯 * 維護播放器信息統一 */ }
實現 getSubscribedEvents 方法,完成事件的綁定。當事件觸發時,dispatcher 會調用綁定的方法,并將拋出的事件當做參數傳入。
事件綁定的方法 onResponse 可以是任何名字。
在 onResponse 方法中,通過 $event 獲取要操作的對象。
class FmResponseEvent extends Event { const NAME = "fm.response"; // 事件名,事件的唯一標識 protected $request; // 在監聽器里要操作的對象 protected $response; // 在監聽器里要操作的對象 public function __construct (Request $request, Response $response) { $this->request = $request; $this->response = $response; } /** * @return Request */ public function getRequest() { return $this->request; } /** * @return Response */ public function getResponse() { return $this->response; } }
繼承 SymfonyComponentEventDispatcherEvent
在訂閱器的業務邏輯上,需要使用 $request 和 $response 對象,所以本事件包含這兩個類的對象。
$event = new FmResponseEvent($request, $response); $dispatcher->dispatch($event::NAME, $event);
dispathcer 會按照優先級,依次執行訂閱器中事件綁定的方法
原碼解讀class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); private $sorted = array(); /** * 觸發事件 */ public function dispatch($eventName, Event $event) { if ($listeners = $this->getListeners($eventName)) { $this->doDispatch($listeners, $eventName, $event); } return $event; } /** * 根據事件名,搜索監聽器 */ public function getListeners($eventName) { if (empty($this->listeners[$eventName])) { return array(); } if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return $this->sorted[$eventName]; } /** * 換優先級將監聽器排序 * @param string $eventName */ private function sortListeners($eventName) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = array(); foreach ($this->listeners[$eventName] as $priority => $listeners) { foreach ($listeners as $k => $listener) { if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof Closure) { $listener[0] = $listener[0](); $this->listeners[$eventName][$priority][$k] = $listener; } $this->sorted[$eventName][] = $listener; } } } protected function doDispatch($listeners, $eventName, Event $event) { foreach ($listeners as $listener) { if ($event->isPropagationStopped()) { break; } call_user_func($listener, $event, $eventName, $this); } /** * 添加訂閱器 */ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->addListener($eventName, array($subscriber, $params)); } elseif (is_string($params[0])) { $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); } } } } public function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName]); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29914.html
摘要:大家好,推薦下我們團隊自己研發的框架為現代化的準備的。可拔插,擴展性強。借鑒了等優秀框架。有興趣的可以關注下。最渴望有人給我們提交。中文文檔基礎已經寫完,剩下努力寫中。。。 大家好,推薦下我們團隊自己研發的框架:tastphp 為現代化的phper準備的。可拔插,擴展性強。借鑒了Symfony、Laravel、Silex等優秀框架。 有興趣的可以關注下 tastphp。最渴望有人給...
摘要:根據提供的超級全局數組來創建實例上面的代碼有一處需要額外解釋一下,自開始內建的可以通過命令行解釋器來啟動,例如但是內建有一個是將和這兩個請求首部存儲到了和中,為了統一內建服務器和真正的中的請求首部字段所以在這里做了特殊處理。 Request 很多框架都會將來自客戶端的請求抽象成類方便應用程序使用,在Laravel中也不例外。IlluminateHttpRequest類在Laravel框...
摘要:框架組件化改造框架從單體應用到組件化改造的架構升級之路經過一年多的開發框架功能越來越完善也越來越復雜初創時期的單體應用已經無法支撐項目的快速發展于是開發組在年前為版制定了組件化改造的重構方案內容速覽組件化原理包管理基礎知識組件化方案來 date: 2018-3-21 13:22:16title: Swoft| Swoft 框架組件化改造description: Swoft 框架從單體應...
摘要:本文目的是多的組件進行簡單的使用。方法中設置了命令的名稱,即命令中的最后一個單詞方法中定義了該命令的執行過程,即輸出再看看入口文件這里的方法將我們定義的添加到了命令行中。 Symfony的Console組件的簡單使用。 本文目的是多Symfony的Console組件進行簡單的使用。達到這樣的效果: 輸入 php console test 輸出 hello console. ...
摘要:前幾天一哥們,去面試遇到到一個用原生編寫的事件監聽,原題是這樣子滴分割線然后就興致勃勃的去看一下,大神的可以直接忽略,就希望幫到一小部分的人就很開心啦簡單原理就是往里面的掛載一個函數,然后在里面調用這個函數,這么一說是不是覺得很簡單好直接上 前幾天一哥們,去面試遇到到一個用原生js 編寫的事件監聽, 原題是這樣子滴! function EventDispatcher() { } /...
閱讀 1084·2021-10-08 10:04
閱讀 3523·2021-08-05 10:01
閱讀 2278·2019-08-30 11:04
閱讀 1794·2019-08-29 15:29
閱讀 838·2019-08-29 15:12
閱讀 1670·2019-08-26 12:11
閱讀 3115·2019-08-26 11:33
閱讀 1163·2019-08-26 10:23