之前寫到TP3.1的行為擴展是tag();在TP3.2中引入了另一種說法—:鉤子。 我們來看一下TP3.2中的鉤子這個東西: 一:文件流程: 1:/index.php - require './ThinkPHP/ThinkPHP.php'; 2:/ThinkPHP/ThinkPHP.php—- require CORE_PATH.'Think'.EXT; Think\Think:
之前寫到TP3.1的行為擴展是tag();在TP3.2中引入了另一種說法—:鉤子。
我們來看一下TP3.2中的鉤子這個東西:
一:文件流程:
1:/index.php ->require './ThinkPHP/ThinkPHP.php';
2:/ThinkPHP/ThinkPHP.php—->require CORE_PATH.'Think'.EXT; Think\Think::start();
3:/ThinkPHP/Library/Think/Think.class.php—–>App::run();
4:/ThinkPHP/Library/Think/App.class.php 。到這里基本流程就走完了,(這里不說細節);
二:代碼:
1:看一下 App::run()方法:
Hook::listen('app_init');
App::init();
Hook::listen('app_begin');
// Session初始化
if(!IS_CLI){
session(C('SESSION_OPTIONS'));
}
// 記錄應用初始化時間
G('initTime');
App::exec();
Hook::listen('app_end');
return ;
其中的Hook::listen(”)就是用來執行鉤子的,我們可以在app_init這個安插的位置用來獲取應用中安裝的插件。
看一下Hook::listen();
@param @param mixed $params 傳入參數
* @return void
*/
static public function listen($tag, &$params=NULL) {
if(isset(self::$tags[$tag])) {
if(APP_DEBUG) {
G($tag.'Start');
trace('[ '.$tag.' ] --START--','','INFO');
}
foreach (self::$tags[$tag] as $name) {
APP_DEBUG && G($name.'_start');
$result = self::exec($name, $tag,$params);
if(APP_DEBUG){
G($name.'_end');
trace('Run '.$name.' [ RunTime:'.G($name.'_start',$name.'_end',6).'s ]','','INFO');
}
if(false === $result) {
// 如果返回false 則中斷插件執行
return ;
}
}
if(APP_DEBUG) { // 記錄行為的執行日志
trace('[ '.$tag.' ] --END-- [ RunTime:'.G($tag.'Start',$tag.'End',6).'s ]','','INFO');
}
}
return;
}
其中關鍵是:self::exec($name, $tag,$params);
看一下exec的代碼:
/**
* 執行某個插件
* @param string $name 插件名稱
* @param @param Mixed $params 傳入的參數
* @return void
*/
static public function exec($name, $tag,&$params=NULL) {
if(false === strpos($name,'\\')) {
// 插件(多個入口)
$class = "Addons\\{$name}\\{$name}Addon";
}else{
// 行為擴展(只有一個run入口方法)
$class = $name.'Behavior';
$tag = 'run';
}
$addon = new $class();
return $addon->$tag($params);
}
最后還不是 new $class();
進而return $addon->$tag($params);
又轉到了具體鉤子的代碼方法。其實就是我們原本的調用class的方法,只不過經過別人的高度封裝了。
三:那么問題來了,這個鉤子有什么用呢? 怎么用?
這里以OneThink 的{:hook('AdminIndex')}
為例,看一些別人是怎么用的。
在系統初始化到 Hook::listen('app_init');
時,
array('Common\Behavior\InitHook')
);
一看就明白,無非就是讀取持久化的信息,放到緩存或是其他的方式
// 行為擴展的執行入口必須是run
public function run(&$content){
if(isset($_GET['m']) && $_GET['m'] === 'Install') return;
$data = S('hooks');
if(!$data){
$hooks = M('Hooks')->getField('name,addons');
foreach ($hooks as $key => $value) {
if($value){
$map['status'] = 1;
$names = explode(',',$value);
$map['name'] = array('IN',$names);
$data = M('Addons')->where($map)->getField('id,name');
if($data){
$addons = array_intersect($names, $data);
Hook::add($key,$addons);
}
}
}
S('hooks',Hook::get());
}else{
Hook::import($data,false);
}
}
當在程序執行到{:hook(‘AdminIndex’)}時—>調用的是Hook::listen(‘AdminIndex’);
AdminIndex這個掛載點包含了三個插件:分別是:SiteStat, SystemInfo,DevTeam。
用一個循環來分別按順序執行.
總結:鉤子其實就是起到一個掛載點的作用,這個鉤子掛在哪里,就可以在哪里執行,內容或功能就是掛載插件或類庫的具體實現。這樣實現的代碼就有很大的靈活性,掛載點不變,掛的東西變量,功能也就相應的變化,是不是很靈活強大呀。
以上只屬于學習筆記,若有錯請指正。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com