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也是类同,运行后效果如图: