CodeIgniter框架钩子机制实现方法【hooks类】


Posted in PHP onAugust 21, 2018

本文实例讲述了CodeIgniter框架钩子机制实现方法。分享给大家供大家参考,具体如下:

记得上一次去到喜啦面试,面试官问我一个问题:codeigniter是如何实现钩子机制的?

当时答不上来,后来回来之后查了一些资料才明白,所以在这里记录一下:

codeigniter的钩子是这样实现的:首先在框架的核心文件system/core/CodeIniter.php文件的 122行,载入Hooks类,接着在该文件中定义了几个挂载点,比如pre_system(129行)、post_controller_constructor(295行)等,并在这些挂载点上面执行hooks类的_call_hook() 方法。

另附codeigniter的hooks类的源代码:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 5.1.6 or newer
 *
 * @package   CodeIgniter
 * @author   EllisLab Dev Team
 * @copyright    Copyright (c) 2008 - 2014, EllisLab, Inc.
 * @copyright    Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
 * @license   http://codeigniter.com/user_guide/license.html
 * @link    http://codeigniter.com
 * @since    Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * CodeIgniter Hooks Class
 *
 * Provides a mechanism to extend the base system without hacking.
 *
 * @package   CodeIgniter
 * @subpackage Libraries
 * @category  Libraries
 * @author   EllisLab Dev Team
 * @link    http://codeigniter.com/user_guide/libraries/encryption.html
 */
class CI_Hooks {

  /**
   * Determines wether hooks are enabled
   *
   * @var bool
   */
  var $enabled    = FALSE;
  /**
   * List of all hooks set in config/hooks.php
   *
   * @var array
   */
  var $hooks     = array();
  /**
   * Determines wether hook is in progress, used to prevent infinte loops
   *
   * @var bool
   */
  var $in_progress  = FALSE;

  /**
   * Constructor
   *
   */
  function __construct()
  {
    $this->_initialize();
    log_message('debug', "Hooks Class Initialized");
  }

  // --------------------------------------------------------------------

  /**
   * Initialize the Hooks Preferences
   *
   * @access private
   * @return void
   */
  function _initialize()
  {
    $CFG =& load_class('Config', 'core');

    // If hooks are not enabled in the config file
    // there is nothing else to do

    if ($CFG->item('enable_hooks') == FALSE)
    {
      return;
    }

    // Grab the "hooks" definition file.
    // If there are no hooks, we're done.

    if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))
    {
      include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');
    }
    elseif (is_file(APPPATH.'config/hooks.php'))
    {
      include(APPPATH.'config/hooks.php');
    }


    if ( ! isset($hook) OR ! is_array($hook))
    {
      return;
    }

    $this->hooks =& $hook;
    $this->enabled = TRUE;
  }

  // --------------------------------------------------------------------

  /**
   * Call Hook
   *
   * Calls a particular hook
   *
   * @access private
   * @param  string the hook name
   * @return mixed
   */
  function _call_hook($which = '')
  {
    if ( ! $this->enabled OR ! isset($this->hooks[$which]))
    {
      return FALSE;
    }

    if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0]))
    {
      foreach ($this->hooks[$which] as $val)
      {
        $this->_run_hook($val);
      }
    }
    else
    {
      $this->_run_hook($this->hooks[$which]);
    }

    return TRUE;
  }

  // --------------------------------------------------------------------

  /**
   * Run Hook
   *
   * Runs a particular hook
   *
   * @access private
   * @param  array  the hook details
   * @return bool
   */
  function _run_hook($data)
  {
    if ( ! is_array($data))
    {
      return FALSE;
    }

    // -----------------------------------
    // Safety - Prevents run-away loops
    // -----------------------------------

    // If the script being called happens to have the same
    // hook call within it a loop can happen

    if ($this->in_progress == TRUE)
    {
      return;
    }

    // -----------------------------------
    // Set file path
    // -----------------------------------

    if ( ! isset($data['filepath']) OR ! isset($data['filename']))
    {
      return FALSE;
    }

    $filepath = APPPATH.$data['filepath'].'/'.$data['filename'];

    if ( ! file_exists($filepath))
    {
      return FALSE;
    }

    // -----------------------------------
    // Set class/function name
    // -----------------------------------

    $class   = FALSE;
    $function = FALSE;
    $params    = '';

    if (isset($data['class']) AND $data['class'] != '')
    {
      $class = $data['class'];
    }

    if (isset($data['function']))
    {
      $function = $data['function'];
    }

    if (isset($data['params']))
    {
      $params = $data['params'];
    }

    if ($class === FALSE AND $function === FALSE)
    {
      return FALSE;
    }

    // -----------------------------------
    // Set the in_progress flag
    // -----------------------------------

    $this->in_progress = TRUE;

    // -----------------------------------
    // Call the requested class and/or function
    // -----------------------------------

    if ($class !== FALSE)
    {
      if ( ! class_exists($class))
      {
        require($filepath);
      }

      $HOOK = new $class;
      $HOOK->$function($params);
    }
    else
    {
      if ( ! function_exists($function))
      {
        require($filepath);
      }

      $function($params);
    }

    $this->in_progress = FALSE;
    return TRUE;
  }

}

// END CI_Hooks class

/* End of file Hooks.php */
/* Location: ./system/core/Hooks.php */

可以看出codeigniter实现钩子机制的方式不够优雅,其实完全可以使用观察者模式来实现钩子机制,将挂载点当做监听的事件。

希望本文所述对大家基于CodeIgniter框架的PHP程序设计有所帮助。

PHP 相关文章推荐
php正则
Jul 07 PHP
WindowsXP中快速配置Apache+PHP5+Mysql
Jun 05 PHP
PHP防CC攻击实现代码
Dec 29 PHP
PHP跳转页面的几种实现方法详解
Jun 08 PHP
PHP获取当前url的具体方法全面解析
Nov 26 PHP
php中的curl使用入门教程和常见用法实例
Apr 10 PHP
详解php设置session(过期、失效、有效期)
Nov 12 PHP
PHP登录验证码的实现与使用方法
Jul 07 PHP
php curl操作API接口类完整示例
May 21 PHP
PHP递归统计系统中代码行数
Sep 19 PHP
php如何获取Http请求
Apr 30 PHP
基于PHP的登录和注册的功能的实现
Aug 06 PHP
PHP依赖注入原理与用法分析
Aug 21 #PHP
PHP 二维array转换json的实例讲解
Aug 21 #PHP
PHP删除数组中指定值的元素常用方法实例分析【4种方法】
Aug 21 #PHP
php 将json格式数据转换成数组的方法
Aug 21 #PHP
php正确输出json数据的实例讲解
Aug 21 #PHP
php将从数据库中获得的数据转换成json格式并输出的方法
Aug 21 #PHP
php实现将数据做成json的格式给前端使用
Aug 21 #PHP
You might like
php模拟post行为代码总结(POST方式不是绝对安全)
2012/02/22 PHP
基于在生产环境中使用php性能测试工具xhprof的详解
2013/06/03 PHP
dedecms函数分享之获取某一栏目所有子栏目
2014/05/19 PHP
ThinkPHP中limit()使用方法详解
2016/04/19 PHP
php简单获取复选框值的方法
2016/05/11 PHP
PHP那些琐碎的知识点(整理)
2017/05/20 PHP
thinkPHP框架中执行事务的方法示例
2018/05/31 PHP
PHP实现的无限分类类库定义与用法示例【基于thinkPHP】
2018/08/06 PHP
php写入文件不覆盖的实例讲解
2019/09/17 PHP
THINKPHP5.1 Config的配置与获取详解
2020/06/08 PHP
如何确保JavaScript的执行顺序 之jQuery.html深度分析
2011/03/03 Javascript
ASP.NET jQuery 实例1(在TextBox里面创建一个默认提示)
2012/01/13 Javascript
在jQuery中 关于json空对象筛选替换
2013/04/15 Javascript
Jquery获取和修改img的src值的方法
2014/02/17 Javascript
详解JavaScript跨域总结与解决办法
2016/10/31 Javascript
bootstrap多层模态框滚动条消失的问题
2017/07/21 Javascript
vue-cli的eslint相关用法
2017/09/29 Javascript
AngularJS实现的锚点楼层跳转功能示例
2018/01/02 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
2019/04/14 Javascript
Swiper.js实现移动端元素左右滑动
2019/09/08 Javascript
浅谈React中组件逻辑复用的那些事儿
2020/05/21 Javascript
python动态参数用法实例分析
2015/05/25 Python
django 删除数据库表后重新同步的方法
2018/05/27 Python
python3实现zabbix告警推送钉钉的示例
2019/02/20 Python
Python玩转PDF的各种骚操作
2019/05/06 Python
提升Python效率之使用循环机制代替递归函数
2019/07/23 Python
python中用logging实现日志滚动和过期日志删除功能
2019/08/20 Python
python之生成多层json结构的实现
2020/02/27 Python
使用python批量转换文件编码为UTF-8的实现
2020/04/03 Python
python drf各类组件的用法和作用
2021/01/12 Python
Ajax实现页面无刷新留言效果
2021/03/24 Javascript
远程研修随笔感言
2014/02/10 职场文书
外联部演讲稿
2014/05/24 职场文书
道德与公民自我评价
2015/03/09 职场文书
导游词之茶卡盐湖
2019/11/26 职场文书
css布局巧妙技巧之css三角示例的运用
2022/03/16 HTML / CSS