Thinkphp事件機(jī)制兩種實(shí)現(xiàn)方式詳解
事件機(jī)制的實(shí)現(xiàn)有兩種途徑:通過(guò)監(jiān)聽(tīng)、通過(guò)訂閱
一、通過(guò)監(jiān)聽(tīng)
1、創(chuàng)建監(jiān)聽(tīng)類:在命令行模式下進(jìn)入框架根目錄執(zhí)行
php think make:listener <自定義的類名>
例如:
php think make:listener UserListener
執(zhí)行之后將在<框架根目錄>\app\listener\下生成UserListener這個(gè)類。
2、配置監(jiān)聽(tīng):在<框架根目錄>\app\event.php這個(gè)文件的listen數(shù)組中配置UserListener這個(gè)類,如下:
'listen' => [
'testEvent' => ['app\listener\UserListener']
],
3、觸發(fā)監(jiān)聽(tīng):在你需要觸發(fā)監(jiān)聽(tīng)的地方加入如下代碼
event('testEvent');注意:這里的參數(shù)testEvent即為事件名稱,可隨便定義,但必須要與在event.php文件里配置的鍵名一致。
觸發(fā)監(jiān)聽(tīng)時(shí)你可以帶上第二個(gè)參數(shù)。通過(guò)第二個(gè)參數(shù)你可以把任何數(shù)據(jù)傳遞到UserListener這個(gè)類中,也就是handle方法的參數(shù)(不明白啥意思的結(jié)合下面的完整代碼理解)。
4、處理監(jiān)聽(tīng)邏輯:在UserListener類的handle方法中完成業(yè)務(wù)邏輯
完整代碼如下
Other:一個(gè)用來(lái)測(cè)試的類
<?php
namespace app\controller;
class Other
{
public function hello()
{
echo 'hello function';
}
}Index:觸發(fā)監(jiān)聽(tīng)的類
<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
public $name = 'index';
public function test1()
{
//觸發(fā)監(jiān)聽(tīng)事件,無(wú)參數(shù)
event('testEvent');
}
public function test2()
{
//觸發(fā)監(jiān)聽(tīng)事件,傳遞字符串
event('testEvent', 'hello');
}
public function test3()
{
//觸發(fā)監(jiān)聽(tīng)事件,傳遞自身類
event('testEvent', $this);
}
public function test4()
{
//觸發(fā)監(jiān)聽(tīng)事件,傳遞其他類
$other = new Other();
event('testEvent', $other);
}
}UserListener:事件監(jiān)聽(tīng)類
<?php
namespace app\listener;
class UserListener
{
/**
* 事件監(jiān)聽(tīng)處理
*
* @return mixed
*/
public function handle($event)
{
//當(dāng)調(diào)用Index類的test1方法時(shí)該代碼有效,$event為null
var_dump($event);
//當(dāng)調(diào)用Index類的test2方法時(shí)該代碼有效,$event為字符串hello
var_dump($event);
//當(dāng)調(diào)用Index類的test3方法時(shí)該代碼有效,$event為Index類的實(shí)例
//可以訪問(wèn)Index類的name變量
echo $event->name;
//當(dāng)調(diào)用Index類的test4方法時(shí)該代碼有效,$event為Other類的實(shí)例
//可以調(diào)用Other類的hello方法
echo $event->hello();
}
}二、通過(guò)訂閱
1、創(chuàng)建訂閱類
在命令行模式下進(jìn)入框架根目錄執(zhí)行
php think make:subscribe <自定義的類名>
例如:
php think make:subscribe UserSubscribe
執(zhí)行之后將在<框架根目錄>\app\subscribe\下生成UserSubscribe這個(gè)類。
2、配置監(jiān)聽(tīng)
在<框架根目錄>\app\event.php這個(gè)文件的subscribe數(shù)組中配置UserSubscribe這個(gè)類,如下:
'subscribe' => ['app\subscribe\UserSubscribe'],
注意:為了測(cè)試效果,要把上面配置的UserListener從listen數(shù)組刪除掉
3、觸發(fā)監(jiān)聽(tīng)
跟第一種途徑一樣
4、處理監(jiān)聽(tīng)邏輯
處理監(jiān)聽(tīng)的邏輯又有兩種方法,我稱之為自動(dòng)綁定和手動(dòng)綁定。手動(dòng)綁定和自動(dòng)綁定是互斥的,只能二選一。
4.1 自動(dòng)綁定
在UserSubscribe類中添加ontestEvent方法,在該方法中完成業(yè)務(wù)邏輯。添加的方法名不能隨意定義,規(guī)則是事件名稱前面加上on。因?yàn)槲覀冊(cè)趀vent.php里定義的事件名稱是testEvent,所以方法名就是ontestEvent(注意大小寫)。監(jiān)聽(tīng)方法定義之后就自動(dòng)與事件綁定,所以我稱之為自動(dòng)綁定。
完整代碼如下
Other和Index類的代碼跟第一種途徑一樣
UserSubscribe:事件訂閱類
<?php
namespace app\subscribe;
class UserSubscribe
{
public function ontestEvent($user)
{
//當(dāng)調(diào)用Index類的test1方法時(shí)該代碼有效,$event為null
var_dump($user);
//當(dāng)調(diào)用Index類的test2方法時(shí)該代碼有效,$event為字符串hello
var_dump($user);
//當(dāng)調(diào)用Index類的test3方法時(shí)該代碼有效,$event為Index類的實(shí)例
//可以訪問(wèn)Index類的name變量
echo $user->name;
//當(dāng)調(diào)用Index類的test4方法時(shí)該代碼有效,$event為Other類的實(shí)例
//可以調(diào)用Other類的hello方法
echo $user->hello();
}
}4.2 手動(dòng)綁定
首先,創(chuàng)建事件類,負(fù)責(zé)處理具體的業(yè)務(wù)邏輯。在命令行模式下進(jìn)入框架根目錄執(zhí)行:
php think make:event <自定義的類名>
例如:
php think make:event UserEvent
執(zhí)行之后將在<框架根目錄>\app\event\下生成UserEvent這個(gè)類。
再在該類中定義一個(gè)handle方法,該方法有一個(gè)傳入?yún)?shù)。方法名和傳入的參數(shù)名可以任意定義。具體的業(yè)務(wù)邏輯就可以放在handle方法里面處理。
然后,在UserSubscribe類中添加subscribe方法,該方法傳入?yún)?shù)為 Event 對(duì)象。然后在該方法中將監(jiān)聽(tīng)的事件綁定到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)
{
//當(dāng)調(diào)用Index類的test1方法時(shí)該代碼有效,$user為null
var_dump($user);
//當(dāng)調(diào)用Index類的test2方法時(shí)該代碼有效,$user為字符串hello
var_dump($user);
//當(dāng)調(diào)用Index類的test3方法時(shí)該代碼有效,$user為Index類的實(shí)例
//可以訪問(wèn)Index類的name變量
echo $user->name;
//當(dāng)調(diào)用Index類的test4方法時(shí)該代碼有效,$user為Other類的實(shí)例
//可以調(diào)用Other類的hello方法
echo $user->hello();
}
}總結(jié)
1、通過(guò)監(jiān)聽(tīng)的方式,每個(gè)事件都需要定義一個(gè)監(jiān)聽(tīng)類來(lái)處理監(jiān)聽(tīng)邏輯,并且在event.php的listen數(shù)組中配置
2、通過(guò)訂閱的方式,如果采用自動(dòng)綁定,則需要在訂閱類中為每個(gè)事件定義一個(gè)監(jiān)聽(tīng)方法(方法名不能自己定義),不需要定義subscribe方法;如果采用手動(dòng)綁定,則定義subscribe方法,并為每一個(gè)事件綁定負(fù)責(zé)處理業(yè)務(wù)邏輯的具體方法(方法名可以自己定義)
3、通過(guò)監(jiān)聽(tīng)的方式中,事件類基本上可有可無(wú),因?yàn)閯?chuàng)建的監(jiān)聽(tīng)類本來(lái)就是專門處理對(duì)應(yīng)的事件的業(yè)務(wù)邏輯的。并且監(jiān)聽(tīng)類可以用事件類代替。
4、通過(guò)訂閱的方式中,如果采用自動(dòng)綁定,事件類也沒(méi)有必要,因?yàn)樵谟嗛嗩愔袨槊總€(gè)事件定義的監(jiān)聽(tīng)方法本來(lái)就是專門處理對(duì)應(yīng)的事件的業(yè)務(wù)邏輯的。如果采用手動(dòng)綁定,也可以把監(jiān)聽(tīng)方法寫在訂閱類中,那么事件類也就沒(méi)必要了。但是個(gè)人認(rèn)為手動(dòng)綁定還是使用事件類比較好。訂閱類只負(fù)責(zé)綁定,事件類負(fù)責(zé)處理具體業(yè)務(wù)邏輯,這樣結(jié)構(gòu)上比較清晰
5、其實(shí)通過(guò)監(jiān)聽(tīng)的方式中,監(jiān)聽(tīng)類(例子中的UserListener)可以替換成其他命名空間下的其他類,只要該類有一個(gè)handle方法就行,比如事件類。替換之后記得要在event.php配置文件中做對(duì)應(yīng)修改。同理,通過(guò)訂閱的方式中,也可以將訂閱類(例子中的UserSubscribe)直接替換為其他類,但是要記得自動(dòng)綁定需要在該類下有符合命名規(guī)則的方法,手動(dòng)綁定需要在該類下有一個(gè)subscribe方法
以上就是Thinkphp事件機(jī)制兩種實(shí)現(xiàn)方式詳解的詳細(xì)內(nèi)容,更多關(guān)于Thinkphp事件機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
php使用環(huán)形鏈表解決約瑟夫問(wèn)題完整示例
這篇文章主要介紹了php使用環(huán)形鏈表解決約瑟夫問(wèn)題,簡(jiǎn)單描述了約瑟夫問(wèn)題并結(jié)合實(shí)例形式分析了php基于環(huán)形鏈表解決約瑟夫問(wèn)題的相關(guān)操作技巧,注釋中包含較為詳盡的說(shuō)明便于理解,需要的朋友可以參考下2018-08-08
escape unescape的php下的實(shí)現(xiàn)方法
escape unescape的php下的實(shí)現(xiàn)方法...2007-04-04
實(shí)現(xiàn)php刪除鏈表中重復(fù)的結(jié)點(diǎn)
在本篇文章中,我們給大家?guī)?lái)了關(guān)于php刪除鏈表中重復(fù)的結(jié)點(diǎn)的相關(guān)知識(shí)點(diǎn)內(nèi)容以及相關(guān)代碼,有興趣的朋友們參考下。2018-09-09
PHP中copy on write寫時(shí)復(fù)制機(jī)制介紹
這篇文章主要介紹了PHP中copy on write寫時(shí)復(fù)制機(jī)制介紹,需要的朋友可以參考下2014-05-05
PHP中static關(guān)鍵字原理的學(xué)習(xí)研究分析
PHP中static關(guān)鍵字原理的學(xué)習(xí)研究分析,學(xué)習(xí)php的朋友可以參考下。2011-07-07
php+mysql+jquery實(shí)現(xiàn)日歷簽到功能
本文主要介紹了php+mysql+jquery實(shí)現(xiàn)日歷簽到功能的過(guò)程與步驟,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02
php判斷類是否存在函數(shù)class_exists用法分析
這篇文章主要介紹了php判斷類是否存在函數(shù)class_exists用法,實(shí)例分析了PHP針對(duì)類是否存在進(jìn)行判斷的應(yīng)用,對(duì)于自動(dòng)加載類以及類實(shí)例化之前的存在判斷來(lái)說(shuō)都非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-11-11
PHP 登錄完成后如何跳轉(zhuǎn)上一訪問(wèn)頁(yè)面
訪問(wèn)網(wǎng)站頁(yè)面時(shí),有的頁(yè)面需要授權(quán)才能訪問(wèn),這時(shí)候就會(huì)要求用戶登錄,跳轉(zhuǎn)到登錄頁(yè)面login.php,怎么實(shí)現(xiàn)登錄后返回到剛才訪問(wèn)的頁(yè)面2014-01-01

