关于onethink的插架的执行过程,以后台首页的{:hook('AdminIndex')}
为例开始进行分析,此方法为
function hook($hook,$params=array()){
\Think\Hook::listen($hook,$params);
}
hook方法接着调用了
onethink\ThinkPHP\Library\Think\Hook.class.php
下的listen方法,listen方法接着调用了当前文件下的exec方法,此时插件开始执行
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;
}
static public function exec($name, $tag,&$params=NULL) {
if('Behavior' == substr($name,-8) ){
// 行为扩展必须用run入口方法
$tag = 'run';
}
$addon = new $name();
return $addon->$tag($params);
}
在listen方法中输出一下当前的类静态数组tags,输出如下图所示:
即在exec方法中,对于AdminIndex,代码
$addon = new $name();
return $addon->$tag($params);
\\相当于执行
$addon = new Addons\SiteStat\SiteStatAddon();
return $addon->AdminIndex();
现在有一个问题,就是tags数组是何时进行赋值的,在上图中我们看到一些框架本身的一些行为扩展,它们又是何时进行加载的。
在onethink\ThinkPHP\Library\Think\Think.class.php
中的start方法进行了app_init的加载,加载代码如下:
if(is_file(CONF_PATH.'tags.php'))
Hook::import(include CONF_PATH.'tags.php');
在start方法的最后执行了App::run();
在run方法中完成了app_init的执行,代码在下方
include的内容在onethink\Application\Common\Conf\tags.php
文件中如下
return array(
'app_init'=>array('Common\Behavior\InitHookBehavior')
);
此时完成了安排app_init的加载,app_init的执行在onethink\ThinkPHP\Library\Think\App.class.php
文件的run方法中,代码如下:
static public function run() {
// 应用初始化标签
Hook::listen('app_init');#此时执行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 ;
}
由一开始的listen方法调用exec方法,此时将执行app_init所对应的InitHookBehavior的run方法 代码如下:
public function run(&$content){
if(defined('BIND_MODULE') && BIND_MODULE === 'Install') return;
$data = S('hooks');
if(!$data){
$hooks = M('Hooks')->getField('name,addons');
dump($hooks);
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 ($key == 'AdminIndex') {
dump($names);
dump($data);
exit;
}
if($data){
$addons = array_intersect($names, $data);
Hook::add($key,array_map('get_addon_class',$addons));
}
}
}
S('hooks',Hook::get());
}else{
Hook::import($data,false);
}
}
代码中三处dump的输出如下:
然后使用Hook类的add方法完成所有在用插件的加载,即将这些插件信息保存到tags数组中