為了獲取更多最新內(nèi)容及功能更新,請(qǐng)直接訪問我們的首頁以查看DzzOffice筆記的最新地址。
鉤子,即行為擴(kuò)展,是一種較為抽象的概念。它可被視為應(yīng)用程序執(zhí)行過程中的廣義上,無論是大型業(yè)務(wù)邏輯,還是小型瀏覽器檢測(cè)、多語言檢測(cè)等,均可被視為一種行為。甚至您希望為網(wǎng)站用戶的首次訪問彈出一個(gè)“Hello, World!”的提示,也可視為一種行為。行為的存在使得無需修改框架和應(yīng)用,即可通過外圍擴(kuò)展或配置來更改或添加功能。不同的行為之間還可能具有相同的位置屬性,例如,某些行為作用于應(yīng)用執(zhí)行前,而某些行為作用于模板輸出后。我們將這些行為發(fā)生作用的位置稱為標(biāo)簽(位)(tag)。當(dāng)應(yīng)用程序運(yùn)行至該標(biāo)簽時(shí),將被攔截并執(zhí)行相關(guān)行為。為便于開發(fā)和拓展,我們?cè)贒zzOffice 2.0中增加了相應(yīng)的處理邏輯。
core\class\dzz\Hook.php 提供了以下處理方法:
/**
* 動(dòng)態(tài)添加行為擴(kuò)展到某個(gè)標(biāo)簽
* @param string $tag 標(biāo)簽名稱
* @param string $behavior 行為名稱(即對(duì)于鉤子處理程序)
* @param bool $first 是否放到開頭執(zhí)行
* @return void
*/
Hook::add($tag, $behavior, $first = false)
/**
* 批量導(dǎo)入
* @param array $tags 插件信息
* @param boolean $recursive 是否遞歸合并
*/
Hook::import(array $tags, $recursive = true)
/**
*
* @param string $tag 留空獲取全部
* @return array
*/
Hook::get($tag = '')
/**
* @param string $tag 標(biāo)簽名稱
* @param mixed $params 傳入?yún)?shù)
* @param mixed $extra 額外參數(shù)
* @param bool $once 只獲取一個(gè)有效返回值
* @return mixed
*/
Hook::listen($tag, &$params = null, $extra = null,$once = false)
在 core\class\dzz\dzz_app.php 中,有以下代碼:
//初始化之前導(dǎo)入數(shù)據(jù)庫鉤子
private function _init_hook(){
$tagfile = CACHE_DIR . BS . 'tags' . EXT;
$data = array();
if (file_exists($tagfile)) {//文件存在則導(dǎo)入文件
$data=include $tagfile;
//if(is_array($data)) $data=array_unique($data);
}
if($data){
Hook::import($data);
}else{
foreach(DB::fetch_all("SELECT name,addons FROM %t where `status`='1' ORDER BY priority DESC",array('hooks')) as $value) {
$addons = $value['addons'];//同一個(gè)掛載點(diǎn)下多個(gè)鉤子改為多條記錄
Hook::add($value['name'],$addons);
}
//寫入緩存文件
$data = Hook::get();
@file_put_contents($tagfile,"<?php \t\n return ".var_export($data,true).";");
}
}
該處理將注冊(cè)系統(tǒng)所有的鉤子,默認(rèn)生成 data/cache/tags.php 緩存文件,并在判斷緩存文件存在時(shí)進(jìn)行注冊(cè)。對(duì)應(yīng)鉤子數(shù)據(jù)庫表前綴_hooks表存儲(chǔ)示例如下:
說明:上圖列出了2個(gè)掛載點(diǎn),分別對(duì)應(yīng)部門向上同步和用戶向上同步的兩個(gè)掛載點(diǎn)。這兩個(gè)掛載點(diǎn)下分別掛載了兩個(gè)鉤子程序(1. 釘釘?shù)挠脩敉剑?. 企業(yè)微信的用戶同步)。addons為鉤子程序?qū)?yīng)類庫文件路徑。name即為標(biāo)簽位(掛載點(diǎn))。調(diào)用 Hook::listen('syntoline_user', $param); 將執(zhí)行該掛載點(diǎn)下的兩個(gè)程序,即釘釘應(yīng)用的用戶同步和企業(yè)微信應(yīng)用的用戶同步。
應(yīng)用的鉤子程序目錄位于應(yīng)用下的 classes 目錄(即命名空間類庫目錄,可使用命名空間定義),例如:dzz/dingtalk/classes/dingtalk.php。應(yīng)用的鉤子程序配置在對(duì)應(yīng)應(yīng)用目錄下的dzz_app_應(yīng)用名.xml文件中配置(如dzz/dingtalk/dzz_app_dingtalk.xml),格式如下:
1.首先添加 item 對(duì)應(yīng)的 hooks 模塊,如上所示,id='hooks' 的 item 即為;
2.每條鉤子對(duì)應(yīng)一個(gè) item,id 對(duì)應(yīng)標(biāo)簽位(掛載點(diǎn));3.priority 對(duì)應(yīng)優(yōu)先級(jí)(可忽略),若有與系統(tǒng)默認(rèn)鉤子同名或同一鉤子需執(zhí)行多個(gè)處理程序,可定義優(yōu)先級(jí)以保證執(zhí)行順序,優(yōu)先級(jí)以數(shù)值大小來區(qū)分,數(shù)值越大優(yōu)先級(jí)越高;4.description 對(duì)應(yīng)描述(可忽略);5.cdata 對(duì)應(yīng)鉤子程序路徑,如需定義鉤子執(zhí)行作用域,可在路徑添加 “|作用域(命名空間方式指定,中間分割符用/)”,如上定義標(biāo)簽位 test,在 test 應(yīng)用下運(yùn)行時(shí)(即用 Hook::listen('test') 調(diào)用),將先執(zhí)行 dzz\test\classes\test 對(duì)應(yīng)處理程序,后執(zhí)行 dzz\test\classes\testa 對(duì)應(yīng)處理程序。若非 test 應(yīng)用下,將只執(zhí)行 dzz\test\classes\test。
鉤子類文件以“.php”為后綴,要求類名和文件名一致,類名稱首字母大寫。鉤子方法定義時(shí),建議與標(biāo)簽位名稱一致。系統(tǒng)執(zhí)行時(shí),將自動(dòng)在對(duì)應(yīng)類文件中尋找該標(biāo)簽位名稱方法。如果沒有,則默認(rèn)執(zhí)行 run 方法(即鉤子方法需與標(biāo)簽位名稱一致或用 run 來命名)。系統(tǒng)默認(rèn)鉤子,均使用命名空間定義,根據(jù)需要可不用亦可。在鉤子方法中,一旦執(zhí)行 return false;,則該標(biāo)簽位(掛載點(diǎn))下無論是否還有其它鉤子程序,都將不再執(zhí)行。應(yīng)用導(dǎo)入或安裝時(shí)將根據(jù)應(yīng)用文件 xml 中的 item 里的 hooks 模塊配置。安裝后更新系統(tǒng)緩存以驗(yàn)證鉤子程序是否正確調(diào)用。
更多建議: