Hook的實現,已經通過tag,顯示出頁面的trace:
Hook裏面只有三個成語函數,無非就是將tag導入,然後在某個適當的位置,調用listen,然後listen就會對這個標籤進行解析,如果存在這個標籤,那麼就調用這個標籤。
這樣,通過這種方法,第三方開發人員就可以非常容易地擴展thinkphp的功能了。
比如:接下來,我們要基於我們以前所寫出的框架,然後實現在app::run這個函數被調用時輸出app::run被調用,然後,再在app::run結束調用時,輸出app::run結束調用這個功能。
首先,是實現我們的hook類,在hook類中,目前只有三個方法,一個是導入,一個監聽,另一個是執行。
<?php
namespace Think;
class Hook{
staticprivate $tags=array();
staticfunction exec($name,$tag,&$params=NULL){
if('Behavior'==substr($name,-8)){
$tag='run';
}
$addon=new$name();//實例化
return$addon->$tag($params);//調用
}
staticfunction import($data,$recursive=true){
if($recursive){//直接覆蓋等於真,直接合並數組便可以
self::$tags=array_merge(self::$tags,$data);
}else{
//如果不是直接覆蓋
}
}
staticfunction listen($tag,&$params=NULL){
if(isset(self::$tags[$tag])){//如果存在某個插件
foreach(self::$tags[$tag]as $name){
$resule=self::exec($name,$tag,$params);
}
}
}
}
然後,再在我們的app:;run方法中,補充上兩條語句。
staticfunction run(){
//環境初始化
self::init();
Hook::listen('app_begin');
self::exec();
Hook::listen('app_end');
}
到後標籤的執行動作我們還需要導入,所以在think.class.php中補充上:
staticfunction start(){
//註冊AUTOLOAD方法
spl_autoload_register('Think\Think::autoload');
Storage::connect();//storage初始化
Storage::read();//調用read方法
//讀取核心類庫
$mode=include MODE_PATH.'common.php';
foreach($mode['core'] as $file){
if(is_file($file)){
include$file;
}
}
//導入標籤
if(isset($mode['tags'])){
Hook::import($mode['tags']);
}
App::run();
}
然後再在我們的模式中添加tags數組便可以了:
'tags' => array(
'app_begin' => array(
'Behavior\AppStartBehavior',
),
'app_end' => array(
'Behavior\AppEndBehavior',
)
)
因爲在hook::exec中,這些行爲也會通過Think::autoload自動導入的,所以路徑會變成是LIB_ATH. 'Behavior\AppStartBehavior',因此,我們需要在Library這個目錄下,創建一個Behavior這個目錄,用來存放這種行爲的文件:
APPEndBehavior類中必須要有run這個函數,因此:
<?php
namespace Behavior;
class AppEndBehavior{
functionrun(){
echo'APP_end';
}
}
Start也是類同,運行後效果如圖: