成人精品一区二区三区中文字幕-成人精品一区二区三区-成人精品一级毛片-成人精品亚洲-日本在线视频一区二区-日本在线视频免费

導(dǎo)航首頁(yè) ? 技術(shù)教程 ? 詳解EventDispatcher事件分發(fā)組件
全站頭部文字 我要出現(xiàn)在這里
詳解EventDispatcher事件分發(fā)組件 715 2024-01-10   

引言

考慮這樣一個(gè)問題,現(xiàn)在你想給為你的項(xiàng)目提供一個(gè)插件系統(tǒng),插件可以添加一些方法,或者在某些方法執(zhí)行之前或者之后做些事情,而不干擾其他插件。要實(shí)現(xiàn)這個(gè)系統(tǒng),簡(jiǎn)單的單繼承不是個(gè)好辦法,即使多繼承在PHP中是可能的,他也有與生俱來的缺點(diǎn)(多繼承不太了解,感覺挺操蛋的)。

Symfony EventDispatcher以一個(gè)簡(jiǎn)單有效的方式實(shí)現(xiàn)了中介者模式,事件分發(fā)器就是那個(gè)中介,讓系統(tǒng)和插件不會(huì)耦合在一起,這讓上面的插件系統(tǒng)成為可能,而且他會(huì)讓你的項(xiàng)目可擴(kuò)展性更好。

上面的話,翻譯自Symfony官方文檔片段

系統(tǒng)剖析

事件存儲(chǔ)

查看圖片

上面這張圖是分析Symfony EventDispatcher組件源碼得出來的,可以看到事件在系統(tǒng)中是如何存儲(chǔ)的

這里面將事件存儲(chǔ)了兩遍,用來加入優(yōu)先級(jí)priority的概念,存如的時(shí)候放入上圖中上面的結(jié)構(gòu)中,取出時(shí)候從上圖中下面的結(jié)構(gòu)中拿出來,相同的事件名稱可以有不同的優(yōu)先級(jí),優(yōu)先級(jí)越高的事件優(yōu)先觸發(fā),優(yōu)先級(jí)相同的時(shí)候,先插入的事件優(yōu)先觸發(fā)。

排序事件(上圖中下面的結(jié)構(gòu))在插入事件的時(shí)候不會(huì)構(gòu)建,而是當(dāng)取出事件的時(shí)候會(huì)生成排好序的事件,當(dāng)相同的事件名中插入新的事件或刪除某個(gè)事件的時(shí)候,會(huì)刪除對(duì)應(yīng)的排好序的事件名,后面用到的時(shí)候重新構(gòu)建

執(zhí)行事件的時(shí)候,會(huì)獲取對(duì)應(yīng)事件名排好序的linster列表,按照順序依次執(zhí)行。

事件執(zhí)行

查看圖片

如上圖所示,當(dāng)觸發(fā)某個(gè)時(shí)間的時(shí)候,該事件名下面如果監(jiān)聽了多個(gè)觸發(fā)動(dòng)作,他們會(huì)按照優(yōu)先級(jí)、注冊(cè)順序依次觸發(fā),觸發(fā)動(dòng)作一般是一個(gè)可執(zhí)行的“實(shí)例”(不管是類還是函數(shù),必須可以通過call_user_func_array調(diào)用),可以傳入三個(gè)參數(shù),第一個(gè)參數(shù)(必須)是一個(gè)Event實(shí)例,第二個(gè)是觸發(fā)的事件名,第三個(gè)是事件分發(fā)器實(shí)例。第一個(gè)參數(shù)會(huì)控制事件是否在該事件名下的所有觸發(fā)動(dòng)作之間繼續(xù)傳遞,比如上面的linstener_2里面將Event.propagationStopped設(shè)置為true,執(zhí)行完linstener_2后,事件就會(huì)停止傳播,linstener_2后面的動(dòng)作不會(huì)觸發(fā)。

除此之外,Event實(shí)例中還可以保存其他必要的信息,以便linstener觸發(fā)執(zhí)行的時(shí)候,獲取額外的信息。

事件訂閱者

查看圖片

事件訂閱者(Event subscriber),告訴dispathcer實(shí)例,他要訂閱的所有事件,不用一個(gè)個(gè)通過dispathcer實(shí)例去注冊(cè)。事件訂閱者是一個(gè)PHP類,他可以告訴dispathcer他要訂閱的具體的事件。

好處:

關(guān)注的事件不用一個(gè)個(gè)去注冊(cè)。 取消關(guān)注的事件不用一個(gè)個(gè)去移除注冊(cè)。

訂閱者內(nèi)部關(guān)注的事件是一個(gè)整體,要么全部關(guān)注要么全部不關(guān)注

實(shí)例

普通栗子

include "vendor/autoload.php";
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentEventDispatcherEvent;
class UserEvent extends Event
{
 public function name()
 {
 return "Cartman";
 }

 public function age()
 {
 return "24";
 }
}
$dispatcher = new EventDispatcher();
$dispatcher->addListener("user.name", function($event, $eventName, $dispatcher){
 echo "My name is Cartmann";
});
$dispatcher->addListener("user.name", function($event, $eventName, $dispatcher){
 echo "My name is {$event->name()} from Event instancen";
}, 10);
$dispatcher->addListener("user.age", function($event, $eventName, $dispatcher){
 echo "My age is 24n";
}, 10);
$dispatcher->addListener("user.age", function($event, $eventName, $dispatcher){
 echo "My age is {$event->age()} from Event instancen";
}, -10);
$dispatcher->dispatch("user.name", new UserEvent());
$dispatcher->dispatch("user.age", new UserEvent());

上面的例子輸出

My name is Cartman from Event instance
My name is Cartman
My age is 24
My age is 24 from Event instance

事件訂閱者栗子

通過Subscriber注冊(cè)事件

include "vendor/autoload.php";
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentEventDispatcherEvent;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
class BookEvent extends Event
{
 public $name = self::class;
}
class BookSubscriber implements EventSubscriberInterface
{
 public static function getSubscribedEvents()
 {
 return [
  "chinese.name" => "chineseNameShow",
  "english.name" => [
  ["englishNameShow", -10],
  ["englishNameAFter", 10],
  ],
  "math.name" => ["mathNameShow", 100]
 ];
 }
 public function chineseNameShow(Event $event)
 {
 echo "我是漢語書籍n";
 }
 public function englishNameShow(Event $event)
 {
 echo "我是英文書籍n";
 }
 public function englishNameAFter(Event $event)
 {
 echo "我是展示之后的英文書籍[來自于Event實(shí)例{$event->name}]n";
 }
 public function mathNameShow(Event $event)
 {
 echo "我是展示的數(shù)學(xué)書籍n";
 }
}
$dispatcher = new EventDispatcher();
$subscriber = new BookSubscriber();
$dispatcher->addSubscriber($subscriber);
$dispatcher->dispatch("english.name", new BookEvent());
$dispatcher->dispatch("chinese.name");
$dispatcher->removeSubscriber($subscriber);
$dispatcher->dispatch("math.name");

輸出為內(nèi)容:

我是展示之后的英文書籍[來自于Event實(shí)例BookEvent]
我是英文書籍
我是漢語書籍

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持綠夏網(wǎng)!



主站蜘蛛池模板: 局中局演员表| 情人电影在线观看高清完整版泰剧| 红白黑黄| 李采潭全部作品| 回到黑暗 电影| 直播斯诺克直播间| 重温经典频道在线直播| 电影《志愿者》观后感| 金福南事件始末在线观看高清影评 | naruto鸣人雏田r18| 仓皇一夜| 性感的护士| 陈若仪个人简历资料| 教师政治学习笔记| 带圈序号1-50| 古天乐电影全部作品最新| 百分百感觉| 北京 北京 汪峰歌曲| 红旗车驾驶员个人主要事迹材料 | 77316电影| 帕瓦德奥特曼| 韩国电影血色对决免费观看| 梁山伯与祝英台电影| 美女搞黄免费| 国产老头视频| 单位同意报考证明| 欲望旅馆| 阿尔法变频器说明书| 免费观看美国破釜沉舟电影| 安吉拉电影| 金太勋| 纳西三部曲| 吴彦祖激情戏| 薛平贵与王宝钏56集免费观看| 昭君出塞简谱| 麻美由真电影| 韩国电影《致命的诱惑》| 每日一句话| 乳糖不耐受奶粉推荐| 无声无息电影| 布袋电影|

!!!站長(zhǎng)長(zhǎng)期在線接!!!

網(wǎng)站、小程序:定制開發(fā)/二次開發(fā)/仿制開發(fā)等

各種疑難雜癥解決/定制接口/定制采集等

站長(zhǎng)微信:lxwl520520

站長(zhǎng)QQ:1737366103