Thinkphp事件機制兩種實現方式詳解

事件機制的實現有兩種途徑:通過監聽、通過訂閱

一、通過監聽

1、創建監聽類:在命令行模式下進入框架根目錄執行

php think make:listener <自定義的類名>

例如:

php think make:listener UserListener

執行之後將在<框架根目錄>\app\listener\下生成UserListener這個類。

2、配置監聽:在<框架根目錄>\app\event.php這個文件的listen數組中配置UserListener這個類,如下:

'listen'    => [
    'testEvent' => ['app\listener\UserListener']
],

3、觸發監聽:在你需要觸發監聽的地方加入如下代碼

event('testEvent');

註意:這裡的參數testEvent即為事件名稱,可隨便定義,但必須要與在event.php文件裡配置的鍵名一致。

觸發監聽時你可以帶上第二個參數。通過第二個參數你可以把任何數據傳遞到UserListener這個類中,也就是handle方法的參數(不明白啥意思的結合下面的完整代碼理解)。

4、處理監聽邏輯:在UserListener類的handle方法中完成業務邏輯

完整代碼如下

Other:一個用來測試的類

<?php
namespace app\controller;
class Other
{
    public function hello()
    {
        echo 'hello function';
    }
}

Index:觸發監聽的類

<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
    public $name  = 'index';
    public function test1()
    {
        //觸發監聽事件,無參數
        event('testEvent');
    }
    public function test2()
    {
        //觸發監聽事件,傳遞字符串
        event('testEvent', 'hello');
    }
    public function test3()
    {
        //觸發監聽事件,傳遞自身類
        event('testEvent', $this);
    }
    public function test4()
    {
        //觸發監聽事件,傳遞其他類
        $other  = new Other();
        event('testEvent', $other);
    }
}

UserListener:事件監聽類

<?php
namespace app\listener;
class UserListener
{
    /**
     * 事件監聽處理
     *
     * @return mixed
     */
    public function handle($event)
    {
        //當調用Index類的test1方法時該代碼有效,$event為null
        var_dump($event);
        //當調用Index類的test2方法時該代碼有效,$event為字符串hello
        var_dump($event);
        //當調用Index類的test3方法時該代碼有效,$event為Index類的實例
        //可以訪問Index類的name變量
        echo $event->name;
        //當調用Index類的test4方法時該代碼有效,$event為Other類的實例
        //可以調用Other類的hello方法
        echo $event->hello();
    }
}

二、通過訂閱

1、創建訂閱類

在命令行模式下進入框架根目錄執行

php think make:subscribe <自定義的類名>

例如:

php think make:subscribe UserSubscribe

執行之後將在<框架根目錄>\app\subscribe\下生成UserSubscribe這個類。

2、配置監聽

在<框架根目錄>\app\event.php這個文件的subscribe數組中配置UserSubscribe這個類,如下:

'subscribe' => ['app\subscribe\UserSubscribe'],

註意:為瞭測試效果,要把上面配置的UserListener從listen數組刪除掉

3、觸發監聽

跟第一種途徑一樣

4、處理監聽邏輯

處理監聽的邏輯又有兩種方法,我稱之為自動綁定和手動綁定。手動綁定和自動綁定是互斥的,隻能二選一。

4.1 自動綁定

在UserSubscribe類中添加ontestEvent方法,在該方法中完成業務邏輯。添加的方法名不能隨意定義,規則是事件名稱前面加上on。因為我們在event.php裡定義的事件名稱是testEvent,所以方法名就是ontestEvent(註意大小寫)。監聽方法定義之後就自動與事件綁定,所以我稱之為自動綁定。

完整代碼如下

Other和Index類的代碼跟第一種途徑一樣

UserSubscribe:事件訂閱類

<?php
namespace app\subscribe;
class UserSubscribe
{
    public function ontestEvent($user)
    {
        //當調用Index類的test1方法時該代碼有效,$event為null
        var_dump($user);
        //當調用Index類的test2方法時該代碼有效,$event為字符串hello
        var_dump($user);
        //當調用Index類的test3方法時該代碼有效,$event為Index類的實例
        //可以訪問Index類的name變量
        echo $user->name;
        //當調用Index類的test4方法時該代碼有效,$event為Other類的實例
        //可以調用Other類的hello方法
        echo $user->hello();
    }
}

4.2 手動綁定

首先,創建事件類,負責處理具體的業務邏輯。在命令行模式下進入框架根目錄執行:

php think make:event <自定義的類名>

例如:

php think make:event UserEvent

執行之後將在<框架根目錄>\app\event\下生成UserEvent這個類。

再在該類中定義一個handle方法,該方法有一個傳入參數。方法名和傳入的參數名可以任意定義。具體的業務邏輯就可以放在handle方法裡面處理。

然後,在UserSubscribe類中添加subscribe方法,該方法傳入參數為 Event 對象。然後在該方法中將監聽的事件綁定到UserEvent類的handle方法上。如下:

$event->listen('testEvent', [app('app\event\UserEvent'), 'handle']);

完整代碼如下

Other和Index類的代碼跟第一種途徑一樣

UserSubscribe:事件訂閱類

<?php
declare (strict_types = 1);
namespace app\subscribe;
use think\Event;
class UserSubscribe
{
    public function subscribe(Event $event)
    {
        $event->listen('testEvent', [app('app\event\UserEvent'), 'handle']);
    }
}

UserEvent:事件處理類

<?php
declare (strict_types = 1);
namespace app\event;
class UserEvent
{
    public function handle($user)
    {
        //當調用Index類的test1方法時該代碼有效,$user為null
        var_dump($user);
        //當調用Index類的test2方法時該代碼有效,$user為字符串hello
        var_dump($user);
        //當調用Index類的test3方法時該代碼有效,$user為Index類的實例
        //可以訪問Index類的name變量
        echo $user->name;
        //當調用Index類的test4方法時該代碼有效,$user為Other類的實例
        //可以調用Other類的hello方法
        echo $user->hello();
    }
}

總結

1、通過監聽的方式,每個事件都需要定義一個監聽類來處理監聽邏輯,並且在event.php的listen數組中配置

2、通過訂閱的方式,如果采用自動綁定,則需要在訂閱類中為每個事件定義一個監聽方法(方法名不能自己定義),不需要定義subscribe方法;如果采用手動綁定,則定義subscribe方法,並為每一個事件綁定負責處理業務邏輯的具體方法(方法名可以自己定義)

3、通過監聽的方式中,事件類基本上可有可無,因為創建的監聽類本來就是專門處理對應的事件的業務邏輯的。並且監聽類可以用事件類代替。

4、通過訂閱的方式中,如果采用自動綁定,事件類也沒有必要,因為在訂閱類中為每個事件定義的監聽方法本來就是專門處理對應的事件的業務邏輯的。如果采用手動綁定,也可以把監聽方法寫在訂閱類中,那麼事件類也就沒必要瞭。但是個人認為手動綁定還是使用事件類比較好。訂閱類隻負責綁定,事件類負責處理具體業務邏輯,這樣結構上比較清晰

5、其實通過監聽的方式中,監聽類(例子中的UserListener)可以替換成其他命名空間下的其他類,隻要該類有一個handle方法就行,比如事件類。替換之後記得要在event.php配置文件中做對應修改。同理,通過訂閱的方式中,也可以將訂閱類(例子中的UserSubscribe)直接替換為其他類,但是要記得自動綁定需要在該類下有符合命名規則的方法,手動綁定需要在該類下有一個subscribe方法

以上就是Thinkphp事件機制兩種實現方式詳解的詳細內容,更多關於Thinkphp事件機制的資料請關註WalkonNet其它相關文章!

推薦閱讀: