行為
概述
| 版本 | 新增功能 |
|---|---|
| 5.0.4 | 行為類的方法采用駝峰法命名 |
| 行為綁定支持綁定到類的方法 |
行(xing)(xing)(xing)為(Behavior)是ThinkPHP擴展(zhan)機制(zhi)中(zhong)(zhong)比(bi)較關鍵(jian)的一項擴展(zhan),行(xing)(xing)(xing)為既可以獨立調(diao)用,也可以綁定到某個標簽(qian)中(zhong)(zhong)進行(xing)(xing)(xing)偵(zhen)聽,在(zai)官方提出的CBD模式(shi)中(zhong)(zhong)行(xing)(xing)(xing)為也占了主要的地位,可見行(xing)(xing)(xing)為在(zai)ThinkPHP框架中(zhong)(zhong)意(yi)義(yi)非凡。
這里指的(de)(de)行(xing)為是(shi)一個(ge)(ge)比較(jiao)抽(chou)象的(de)(de)概念,你可(ke)以(yi)(yi)把行(xing)為想象成在(zai)(zai)應(ying)(ying)用(yong)執(zhi)行(xing)過程中的(de)(de)一個(ge)(ge)動作或(huo)者(zhe)處理。在(zai)(zai)框架(jia)(jia)的(de)(de)執(zhi)行(xing)流程中,例(li)如路由(you)檢(jian)(jian)測(ce)(ce)是(shi)一個(ge)(ge)行(xing)為,靜態(tai)緩存是(shi)一個(ge)(ge)行(xing)為,用(yong)戶權限檢(jian)(jian)測(ce)(ce)也是(shi)行(xing)為,大(da)到業務邏(luo)輯,小到瀏覽器檢(jian)(jian)測(ce)(ce)、多語言(yan)檢(jian)(jian)測(ce)(ce)等等都可(ke)以(yi)(yi)當做是(shi)一個(ge)(ge)行(xing)為,甚至說你希望給(gei)你的(de)(de)網站用(yong)戶的(de)(de)第一次訪問(wen)彈出Hello,world!這些都可(ke)以(yi)(yi)看成是(shi)一種行(xing)為,行(xing)為的(de)(de)存在(zai)(zai)讓你無需改動框架(jia)(jia)和應(ying)(ying)用(yong),而在(zai)(zai)外(wai)圍通過擴展或(huo)者(zhe)配(pei)置來改變或(huo)者(zhe)增加一些功(gong)能。
而(er)不同的(de)(de)行為(wei)之間也具有位置共同性(xing),比(bi)如(ru),有些(xie)行為(wei)的(de)(de)作用(yong)位置都(dou)是(shi)在(zai)應(ying)用(yong)執行前,有些(xie)行為(wei)都(dou)是(shi)在(zai)模板(ban)輸(shu)出之后,我們把這些(xie)行為(wei)發生作用(yong)的(de)(de)位置稱之為(wei)標(biao)簽(qian)(位),當應(ying)用(yong)程序運行到這個標(biao)簽(qian)的(de)(de)時(shi)候,就會(hui)被攔截下來,統一(yi)執行相關的(de)(de)行為(wei),類(lei)似(si)于AOP編程中(zhong)的(de)(de)“切面”的(de)(de)概念,給某一(yi)個切面綁(bang)定相關行為(wei)就成(cheng)了一(yi)種(zhong)類(lei)AOP編程的(de)(de)思想(xiang)。
行為標簽位
在(zai)定義行(xing)為之(zhi)前,我們先來了解下系(xi)統有哪些標簽位,系(xi)統核(he)心提供的標簽位置包括下面幾個(按(an)照執行(xing)順序排列):
| 標簽位 | 描述 |
|---|---|
| app_init | 應用初始化標簽位 |
| app_begin | 應用開始標簽位 |
| module_init | 模塊初始化標簽位 |
| action_begin | 控制器開始標簽位 |
| view_filter | 視圖輸出過濾標簽位 |
| app_end | 應用結束標簽位 |
| log_write | 日志write方法標簽位 |
| log_write_done |
日志寫入完成標簽位(V5.0.10+) |
| response_send |
響應發送標簽位(V5.0.10+) |
| response_end |
輸出結束標簽位(V5.0.1+) |
在每個標簽位置,可(ke)以配置多(duo)個行為(wei)定(ding)義,行為(wei)的執(zhi)行順序按(an)照定(ding)義的順序依次(ci)執(zhi)行。除非前(qian)面(mian)(mian)的行為(wei)里面(mian)(mian)中斷執(zhi)行了(某些行為(wei)可(ke)能需要(yao)中斷執(zhi)行,例如(ru)檢測機器(qi)人或者非法執(zhi)行行為(wei)),否則會繼續下一個行為(wei)的執(zhi)行。
除了這些(xie)系統內置(zhi)標(biao)簽(qian)之外(wai),開發人員還可以在(zai)應用中添加自(zi)己的應用標(biao)簽(qian)。
添加行為標簽位
可以使用\think\Hook類的listen方(fang)法(fa)添加自(zi)己(ji)的行為偵聽位置,例如:
Hook::listen('action_init');
可以給(gei)偵(zhen)聽方(fang)法傳入參(can)數(僅能傳入一個參(can)數),該參(can)數使用引用傳值,因此必須(xu)使用變量(liang),例(li)如:
Hook::listen('action_init',$params);
偵聽的標簽位置可以(yi)隨意(yi)放(fang)置。
行為定義
行為類的定義很簡單,定義行為的執行入口方法run即可,例如:
namespace app\index\behavior;
class Test
{
public function run(&$params)
{
// 行為(wei)邏輯(ji)
}
}
行為類并不需要繼承任何類,相對比(bi)較靈活。
如果行為類需要綁定到(dao)多個標簽,可以(yi)采用如下(xia)定義:
namespace app\index\behavior;
class Test
{
public function app_init(&$params)
{
}
public function app_end(&$params)
{
}
}
綁定到app_init和app_end后 就(jiu)會(hui)調用(yong)相關的方法。
V5.0.4+版本(ben)以(yi)上,行為(wei)類的(de)方法需要采用駝峰法命(ming)名,上面(mian)的(de)行為(wei)類需要改(gai)成:
namespace app\index\behavior;
class Test
{
public function appInit(&$params)
{
}
public function appEnd(&$params)
{
}
}
行為綁定
行為定義完成后,就需要綁定到某個標簽位置才能生效,否則是不會執行的。
使用Hook類的add方法注(zhu)冊行為,例(li)如:
// 注冊 app\index\behavior\CheckLang行為類到app_init標簽位
Hook::add('app_init','app\\index\\behavior\\CheckLang');
//注冊 app\admin\behavior\CronRun行為類到app_init標簽位
Hook::add('app_init','app\\admin\\behavior\\CronRun');
如果(guo)要批量注冊行(xing)為(wei)的話,可(ke)以使用:
Hook::add('app_init',['app\\index\\behavior\\CheckAuth','app\\index\\behavior\\CheckLang','app\\admin\\behavior\\CronRun']);
當應用運行到app_init標簽位的時候,就會依次調用app\index\behavior\CheckAuth、app\index\behavior\CheckLang和app\admin\behavior\CronRun行為。如果其中一個行為中有中止代碼的話則后續不會執行,如果返回false則當前標(biao)簽位(wei)的后續行為將(jiang)不(bu)會執(zhi)行,但應(ying)用將(jiang)繼續運(yun)行。
我們也可以直接在APP_PATH目錄下面或者模塊的目錄下面定義tags.php文(wen)件來(lai)統一(yi)定義行為(wei),定義格式如下:
return [
'app_init'=> [
'app\\index\\behavior\\CheckAuth',
'app\\index\\behavior\\CheckLang'
],
'app_end'=> [
'app\\admin\\behavior\\CronRun'
]
]
如果APP_PATH目錄下面和模塊目錄下面的tags.php都定義了app_init的行為綁定的話,會采用合并模式,如果希望覆蓋,那么可以在模塊目錄下面的tags.php中定義如下:
return [
'app_init'=> [
'app\\index\\behavior\\CheckAuth',
'_overlay'=>true
],
'app_end'=> [
'app\\admin\\behavior\\CronRun'
]
]
如果某個行為標簽定義了'_overlay' =>true 就表(biao)示覆蓋(gai)之前的相(xiang)同標簽下面的行為定義。
閉包支持
可以(yi)不用定義行為直接把(ba)閉包函數綁定到某個標簽位,例如:
Hook::add('app_init',function(){
echo 'Hello,world!';
});
如果標簽位有傳(chuan)入參數的話,閉包也可以支持傳(chuan)入參數,例如:
Hook::listen('action_init',$params);
Hook::add('action_init',function($params){
var_dump($params);
});
直接執行行為
如果需要,你也可(ke)以(yi)不綁定行為(wei)標簽,直接調用(yong)某個行為(wei),使用(yong):
// 執行 app\index\behavior\CheckAuth行為類的run方法 并引用傳入params參數
$result = Hook::exec('app\\index\\behavior\\CheckAuth','run',$params);
