• 技术文章 >后端开发 >PHP问题

    php钩子原理是什么

    爱喝马黛茶的安东尼爱喝马黛茶的安东尼2019-08-28 15:26:40原创2080

    钩子原理很简单,有些人把事情弄的过于发杂,其实就是调用某个目录下的比如/hook目录下注册在hook函数里面和读取hook配置文件里面的类的方法的一个调用类的方法的功能。

    目的就是最少改动代码,改动旧功能,或者增加一些新功能,或者简单说成调用函数都行。

    但是读取hook的配置文件,还是需要在系统的里面每次都需要读取,其实就失去了hook的意义,建议只做钩子本身的就好。

    相关推荐:《PHP入门教程

    参看一下ci的hook,仅截取hook函数核心部分。

    <?php
     protected function _run_hook($data) {
            // Closures/lambda functions and array($object, 'method') callables
            if (is_callable($data)) {
                is_array($data) ? $data[0]->{$data[1]}() : $data();
                return TRUE;
            } elseif (!is_array($data)) {
                return FALSE;
            }
            if ($this->_in_progress === TRUE) {
                return;
            }
            if (!isset($data['filepath'], $data['filename'])) {
                return FALSE;
            }
            $filepath = APPPATH . $data['filepath'] . '/' . $data['filename'];
            if (!file_exists($filepath)) {
                return FALSE;
            }
            $class = empty($data['class']) ? FALSE : $data['class'];
            $function = empty($data['function']) ? FALSE : $data['function'];
            $params = isset($data['params']) ? $data['params'] : '';
            if (empty($function)) {
                return FALSE;
            }
            // Set the _in_progress flag
            $this->_in_progress = TRUE;
            // Call the requested class and/or function
            if ($class !== FALSE) {
                // The object is stored?
                if (isset($this->_objects[$class])) {
                    if (method_exists($this->_objects[$class], $function)) {
                        $this->_objects[$class]->$function($params);
                    } else {
                        return $this->_in_progress = FALSE;
                    }
                } else {
                    class_exists($class, FALSE) OR require_once($filepath);
                    if (!class_exists($class, FALSE) OR ! method_exists($class, $function)) {
                        return $this->_in_progress = FALSE;
                    }
                    // Store the object and execute the method
                    $this->_objects[$class] = new $class(); 
                    $this->_objects[$class]->$function($params);
                 // 核心部分 读取参数部分,去实例化类调用方法 传递参数  其实这也是MVC url路由实现的核心,现在很多
    //都是使用 call_user_func_array  call_user_func 这两个方法
                }
            } else {
                function_exists($function) OR require_once($filepath);
                if (!function_exists($function)) {
                    return $this->_in_progress = FALSE;
                }
                $function($params);
            }
            $this->_in_progress = FALSE;
            return TRUE;
        }

    原理图解

    1566976861978525.png

    个人实现版本

    如果你觉得麻烦,甚至可以写个方法都行,建议写成一个类,因为有些东西需要更多的信息

    1566976876765410.png

    php

    include 'hook.class.php';
    $rr = new hook();
    //$ee = $rr->get_all_class();
    $rr->run_hook('ff','ss',array());
    //echo '<pre>';
    //print_r($ee);
    //echo '</pre>';

    hook.class.php

    class hook {
        public $HOOK_PATH;
        public $PATH; //完整钩子文件目录
        public $object;
        //调用的时候这个类使用的时候,必须在系统的执行流程当中
        public function __construct() {
            $this->HOOK_PATH = ''; //项目的路径,根据你的项目计算路径  
            $current_path = str_replace("\\", "/", getcwd()); //获取当前目录
            //这个地方在实际用的时候看你需要调整
            $this->PATH = $current_path . $this->HOOK_PATH;
        }
        /* 注册钩子 也可以叫做运行钩子
         * $class       类名称
         * $function    方法 
         * $param       方法参数
         */
        public function run_hook($class, $function, $param = array()) {
            include $this->PATH . '/' . $class . '.class.php';
    //        var_dump($this->PATH . '/' . $class . '.class.php');
    //        call_user_func_array(array($class, $function), $param);//只能调用类的静态方法
    //        call_user_func(array($class, $function), $param);  //只能调用类的静态方法
    //        其他写法
            $this->object = new $class();
            $this->object->$function($param); //这样就可以不用调用静态方法
        }
        //返回当前已经所有的钩子类和方法  不要当前方法调用这个核心类,需要稍微改造,在$hook_array[$key]['function']的返回
        方法名的时候
        public function get_all_class() {
            //搜寻hook目录下的所有钩子文件,返回数组
    //        $this->PATH
    //        var_dump($this->PATH);
            $file_array = scandir($this->PATH);
            $hook_array = array();
            foreach ($file_array as $key => $value) {
                if (strpos($value, '.class.php') == true) {     //扫描路径绝对不能和这个类本身在一个同一个目录下,不然
                会出现重复声明的同名类
                    $name = explode('.', $value);
                    $hook_array[$key]['name'] = $name['0'] . '钩子类';
                    $hook_array[$key]['url'] = $this->PATH . '/' . $value;
    //                include $hook_array[$key]['url']; 
    //                $cc = new $name['0']();
    //                $hook_array[$key]['function'][] = get_class_methods($cc);
    //                $hook_array[$key]['function']['param'][] = get_class_vars($class_name); //获取方法变量
                }
            }
            return $hook_array;
        }
    }

    调用的某个类名

    ff.class.php 的ss方法

        public function ss() {
    //    static public function ss() {
            echo 'dddddddddddddddddddd';
        }

    另一个版本

    更方便调用

    class hooks {
        const Directory_Structure = '/hooks/'; //相对目录的路径  具体项目使用的时候需要调整
        static public function get_path() {
            return str_replace("\\", "/", getcwd());
        }
        static public function run_hook($class, $function, $param = array()) {
           $s =  include self::get_path() . self::Directory_Structure .$class. '.class.php';
            call_user_func(array($class, $function), $param);  //只能调用类的静态方法
    //        其他写法
    //        $object = new $class();
    //        $object->$function($param); //这样就可以不用调用静态方法
        }
    }

    使用

    include 'hooks.class.php';
    hooks::run_hook('ee', 'vv',$param =array());
    当然也可以这么访问
    $foo = new hooks();
    $foo->run_hook('ee', 'vv',array());
    $foo::run_hook('ee', 'vv',array());

    自 PHP 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字 self,parent 或 static。

    钩子是比较灵活的,可以额外增加一个功能代码,使代码更整洁,比如在做什么一些重要操作,创建订单,在创建订单之前需要做些什么,在创建之后做些什么,都可以使用钩子,这样代码更加灵活。

    以上就是php钩子原理是什么的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:php 钩子原理
    上一篇:php里缓冲区的作用是什么 下一篇:php合并两个数组的方式有哪些
    大前端线上培训班

    相关文章推荐

    • php无限极分类的原理是什么• php抽象类的作用是什么• php中reg的意思是什么• php里缓冲区的作用是什么

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网