当前位置:Gxlcms > mysql > ThinkPHP3.2扩展

ThinkPHP3.2扩展

时间:2021-07-01 10:21:17 帮助过:45人阅读

之前写到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'); 时,


return array(
    '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。
用一个循环来分别按顺序执行.

总结:钩子其实就是起到一个挂载点的作用,这个钩子挂在哪里,就可以在哪里执行,内容或功能就是挂载插件或类库的具体实现。这样实现的代码就有很大的灵活性,挂载点不变,挂的东西变量,功能也就相应的变化,是不是很灵活强大呀。


以上只属于学习笔记,若有错请指正。

人气教程排行