在不修改CI框架底层的基础上,实现对特定uri的方法主体钩子触发

钩子、行为、中间件这几中概念都是从 aop切面编程 演化过来的

注意配置config/config.php$config['enable_hooks'] = 1

配置config/hooks.php

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
| -------------------------------------------------------------------------
| Hooks
| -------------------------------------------------------------------------
| This file lets you define "hooks" to extend CI without hacking the core
| files.  Please see the user guide for info:
|
|	http://codeigniter.com/user_guide/general/hooks.html
|
*/

/* End of file hooks.php */
/* Location: ./application/config/hooks.php */
//控制器方法执行之前
$hook['post_controller_constructor'] = [
    'class'    => 'hooks_init',
    'function' => 'before_method',
    'filename' => 'hooks_init.php',
    'filepath' => 'hooks',

];

//控制器方法执行之后
$hook['post_controller'] = [
    'class'    => 'hooks_init',
    'function' => 'after_method',
    'filename' => 'hooks_init.php',
    'filepath' => 'hooks',
];

增加钩子公共触发类,并在此类中来实现特定触发逻辑

<?php

class hooks_init extends CI_Hooks
{

    public $CI;

    public $config = [];

    /**
     * hooks_init constructor.
     */
    public function __construct()
    {
        parent::__construct();

        $this->CI = & get_instance();

        $module_name = $this->CI->router->directory;

        $module_name = (string) explode('/',$module_name)[0];

        //类名
        $class_name = $this->CI->router->class;
        //调用方法名
        $method_name = $this->CI->router->method;
        //不同模块的配置文件引入
        $hook_config_filepath = APPPATH."config/aop/{$module_name}.php";

        if( !file_exists($hook_config_filepath) ){
            return false;
        }

        $module_config = require $hook_config_filepath;

        $config_key = "{$class_name}/{$method_name}";

        $this->config = isset($module_config[$config_key]) ? $module_config[$config_key]:"";

        return $this;
    }

    //主体方法调用之前执行
    public function before_method(){

        $config_data = isset($this->config['_before'])?$this->config['_before']:[];

        if(empty($config_data)){
            return false;
        }else{
            return $this->call_function($config_data);
        }

    }

    //主体方法调用之前执行
    public function after_method(){

        $config_data = isset($this->config['_after'])?$this->config['_after']:[];

        if(empty($config_data)){
            return false;
        }else{
            return $this->call_function($config_data);
        }

    }

    private function call_function($config_data){

        if(empty($config_data['filename'])){
            return false;
        }

        $hook_class_filepath = APPPATH.'hooks/'.$config_data['filename'];

        if( !file_exists($hook_class_filepath) ){
            return false;
        }else{
            require_once $hook_class_filepath;
        }

        if(!isset($config_data['class']) || !class_exists($config_data['class'])){
            show_error("{$config_data['class']}该类不存在!");
            die;
        }

        $parmas = isset($config_data['params']) ? $config_data['params'] : [];

        $function = isset($config_data['function'])? $config_data['function'] : "";

        $hook_obj = new $config_data['class']();

        return call_user_func_array([$hook_obj,$function],$parmas);
    }


}



添加admin模块的钩子配置

config/aop/admin.php


<?php
/**
 * Created by PhpStorm.
 * User: querying
 * Date: 18-5-17
 * Time: 下午2:43
 * Describe: 该配置主要扩展CI框架的钩子功能
 *
 * CI的钩子在全局流程中调用,
 * 但由于并没有针对控制器类的具体方法执行钩子配置,
 * 因此对其进行扩展
 *
 *
 *
 */
//模块名
$hook_nodes = [
    //配置详解
    //类名/方法名
    'admin_login/index' => [
        //方法执行前的钩子配置
        '_before' => [
            //要引入的类
            'class'    => 'require_class_name',
            //要执行的方法
            'function' => 'hook_exec_func_name_before',
            //application/hooks下的文件路径
            'filename' => 'admin/hook_file_path.php',
            //传递的参数
            'params'   => []
        ],
        //方法执行后的钩子配置
        '_after' => [
            //要引入的类
            'class'    => 'require_class_name',
            //要执行的方法
            'function' => 'hook_exec_func_name_after',
            //application/hooks下的文件路径
            'filename' => 'admin/hook_file_path.php',
        ],
    ],
    'admin_keep/add_pdf_file' => [
        //方法执行后的钩子配置
        '_after' => [
            //要引入的类
            'class'    => 'require_class_name',
            //要执行的方法
            'function' => 'hook_exec_func_name_after',
            //application/hooks下的文件路径
            'filename' => 'admin/hook_file_path.php',
        ],
    ],
];



return $hook_nodes;



根据配置文件在hooks/目录下添加各个模块的钩子调用类

demo:

application/hooks/admin/hook_file_path.php

<?php

class require_class_name extends CI_controller
{
    
    public function hook_exec_func_name_after
    {
        //        
        
    }
    
    public function hook_exec_func_name_before
    {
        
    }
    

}


猜你喜欢

转载自my.oschina.net/u/3095457/blog/1822324