事件介紹
使用事件,可以在特定的時點,觸發執行預先設定的一段代碼,事件既是代碼解耦的一種方式,也是設計商務程序的一種模式。現代軟體中,事件無處不在,比如,你發了個微博,觸發了一個事件,導致關注你的人,看到了你新發出來的內容。對於事件而言,有這麼幾個要素:
這是一個什麼事件?一個軟體系統裡,有諸多事件,發布新微博是事件,刪除微博也是一種事件。
誰觸發了事件?你發的微博,就是你觸發的事件。
誰負責監聽這個事件?或者誰能知道這個事件發生了?伺服器上處理使用者註冊的模組,肯定不會收到你發出新微博的事件。
事件怎麼處理?對於發布新微博的事件,就是通知關注了你的其他使用者。
事件相關資料是什嗎?對於發布新微博事件,包含的資料至少要有新微博的內容,時間等
代碼實現
對象層級綁定
案例介紹:有一隻貓,它一叫老鼠就會跑
為了實現這個案例,我們在 frontend 檔案夾中建立 event檔案夾
在 event檔案夾 中2個類檔案,一個Cat類,一個Mouse類
<?phpnamespace frontend\event;/** * 貓類 * Class: \frontend\event\Cat * * 為了讓貓具有事件能力 * 所以要繼承 \yii\base\Component * >>> \yii\base\Component 對 \yii\base\Event 的 on 方法進行重寫 * >>> \yii\base\Event 適合類級綁定 * >>> \yii\base\Component 適合對象級綁定 */class Cat extends \yii\base\Component{ /** * 貓發出叫聲 */ public function shout() { echo '貓:miao miao miao <br />'; // 貓叫了之後 觸發貓的 miao 事件 $this->trigger('miao'); }}
Mouse.php
<?phpnamespace frontend\event;/** * 老鼠類 * Class: \frontend\event\Mouse */class Mouse{ public function run() { echo '老鼠:有貓來了,趕緊跑啊~~<br />'; }}
EventController.php
<?phpnamespace frontend\controllers;use frontend\event\Cat;use frontend\event\Mouse;/*** Class: \frontend\controllers\Event*/class EventController extends \yii\web\Controller{ public function actionTest() { $cat = new Cat(); $mouse = new Mouse(); // 需事先給貓綁定 miao 事件才可以觸發此事件 // 貓一叫,就觸發老鼠的 run 方法 $cat->on('miao', [$mouse, 'run']); // 貓發出叫聲 $cat->shout(); }}
在瀏覽器輸入http://yourdomain.com/?r=event/test
得到
貓:miao miao miao 老鼠:有貓來了,趕緊跑啊~~
通過調用貓的 shout 方法,觸發 miao 事件,老鼠就跑了
突然間,有一天,狗加入這件案例,只要貓一叫,狗就會去找貓
so 也是在event檔案夾中
加入狗成員 Dog.php
<?phpnamespace frontend\event;/** * Class \frontend\event\Dog */class Dog extends \yii\base\Component{ /** * 找貓 */ public function findCat() { echo '狗:wang wang wang, 貓在哪裡??'; }}
修改 frontend/controllers/EventController.php
添加狗找貓事件
...// 需事先給貓綁定 miao 事件才可以觸發此事件// 貓一叫,就觸發老鼠的 run 方法$cat->on('miao', [$mouse, 'run']);$cat->on('miao', [$dog, 'findCat']); // 添加狗找貓事件// 讓貓發出叫聲$cat->shout();...
在瀏覽器中重新整理http://yourdomain.com/?r=event/test
得到
貓:miao miao miao 老鼠:有貓來了,趕緊跑啊~~狗:wang wang wang, 貓在哪裡??
突然間,狗覺得很無聊,不想去找貓了,隨便它叫了
那麼我們只需將狗找貓事件取消綁定
修改 frontend/controllers/EventController.php
use frontend\event\Cat;use frontend\event\Mouse;use frontend\event\Dog;...public function actionTest(){ $cat = new Cat(); $mouse = new Mouse(); $dog = new Dog(); // 需事先給貓綁定 miao 事件才可以觸發此事件 // 貓一叫,就觸發老鼠的 run 方法 $cat->on('miao', [$mouse, 'run']); $cat->on('miao', [$dog, 'findCat']); // 並非直接刪除 $cat->on('miao', [$dog, 'findCat']); // 而是通過 off 解除綁定 $cat->off('miao', [$dog, 'findCat']); // 讓貓發出叫聲 $cat->shout();}...
所以得到的最終結果自然少了狗的聲音
類層級綁定
但是有一個問題,以上事件直針對 $cat 所賦值的對象,
即在 frontend/controllers/EventController.php 中的 actionTest 方法末尾中添加 (new Cat())->shout(); 不會觸發 miao 事件
public function actionTest(){ ... // 讓貓發出叫聲 $cat->shout(); // 會觸發 miao 事件 (new Cat())->shout(); // 不會觸發 miao 事件}
原因:都是通過$cat對象進行事件綁定的
那有沒有一種,只要是貓發出的聲音,老鼠就跑呢??
這就需要用到類層級的事件綁定
類層級事件綁定需要用到 \yii\base\Event類
修改 frontend/controllers/EventController.php
use frontend\event\Cat;use frontend\event\Mouse;use yii\base\Event;...public function actionTest(){ $cat = new Cat(); $mouse = new Mouse(); // 類層級的事件綁定 // 只要貓發出聲音,不管是什麼貓,都會觸發老鼠的 run 方法 Event::on(Cat::className() ,'miao', [$mouse, 'run']); // 讓貓發出叫聲 $cat->shout(); // 會觸發 miao 事件 (new Cat())->shout(); // 會觸發 miao 事件}
重新整理頁面,得到
貓:miao miao miao 老鼠:有貓來了,趕緊跑啊~~貓:miao miao miao 老鼠:有貓來了,趕緊跑啊~~
總結
事件綁定分類對象層級和類層級的綁定
對象層級只針對某一個執行個體化的對象
類層級對所有執行個體化的對象都起效
如果以上理解有錯誤,歡迎提出和指正