onethink的hook机制

来源:互联网 发布:保研夏令营 知乎 编辑:程序博客网 时间:2024/06/07 04:11

关于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文件中如下

         <?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数组中

0 0