原文地址:http://www.cnblogs.com/Hzhihua/p/7352122.html
參考資料:
最近一直在學習Yii2框架,在這記錄自己對Yii2事件的了解
事件介紹
使用事件,可以在特定的時點,觸發執行預先設定的一段代碼,事件既是代碼解耦的一種方式,也是設計業務流程的一種模式。現代軟件中,事件無處不在,比如,你發了個微博,觸發了一個事件,導致關注你的人,看到了你新發出來的內容。對於事件而言,有這么幾個要素:
- 這是一個什么事件?一個軟件系統里,有諸多事件,發布新微博是事件,刪除微博也是一種事件。
- 誰觸發了事件?你發的微博,就是你觸發的事件。
- 誰負責監聽這個事件?或者誰能知道這個事件發生了?服務器上處理用戶注冊的模塊,肯定不會收到你發出新微博的事件。
- 事件怎么處理?對於發布新微博的事件,就是通知關注了你的其他用戶。
- 事件相關數據是什么?對於發布新微博事件,包含的數據至少要有新微博的內容,時間等
代碼實現
對象級別綁定
事例介紹:有一只貓,它一叫老鼠就會跑
為了實現這個事例,我們在 frontend 文件夾中創建 event文件夾
在 event文件夾 中2個類文件,一個Cat類,一個Mouse類
<?php
namespace 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
<?php
namespace frontend\event;
/**
* 老鼠類
* Class: \frontend\event\Mouse
*/
class Mouse
{
public function run()
{
echo '老鼠:有貓來了,趕緊跑啊~~<br />';
}
}
EventController.php
<?php
namespace 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
<?php
namespace 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
老鼠:有貓來了,趕緊跑啊~~
總結
- 事件綁定分類對象級別和類級別的綁定
- 對象級別只針對某一個實例化的對象
- 類級別對所有實例化的對象都起效
如果以上理解有錯誤,歡迎提出和指正
參考資料: