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中,文件上传
Dec 06 PHP
PHP COOKIE设置为浏览器进程
Jun 21 PHP
php ci框架中加载css和js文件失败的原因及解决方法
Jul 29 PHP
php获取用户浏览器版本的方法
Jan 03 PHP
php给图片加文字水印
Jul 31 PHP
php获取远程文件内容的函数
Nov 02 PHP
php基于session锁防止阻塞请求的方法分析
Aug 07 PHP
Windows平台PHP+IECapt实现网页批量截图并创建缩略图功能详解
Aug 02 PHP
php实现QQ小程序发送模板消息功能
Sep 18 PHP
laravel框架创建授权策略实例分析
Nov 22 PHP
通过PHP实现获取访问用户IP
May 09 PHP
aec加密 php_php aes加密解密类(兼容php5、php7)
Mar 14 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之第四天
2006/10/09 PHP
PHP的栏目导航程序
2006/10/09 PHP
用PHP和ACCESS写聊天室(六)
2006/10/09 PHP
php INI配置文件的解析实现分析
2011/01/04 PHP
php计算十二星座的函数代码
2012/08/21 PHP
PHPMailer邮件发送的实现代码
2013/05/04 PHP
CI框架中$this-&gt;load-&gt;library()用法分析
2016/05/18 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
jQuery常见开发技巧详细整理
2013/01/02 Javascript
原生js实现跨浏览器获取鼠标按键的值
2013/04/08 Javascript
简单的Jquery遮罩层代码实例
2013/11/14 Javascript
js清空表单数据的两种方式(遍历+reset)
2014/07/18 Javascript
分享使用AngularJS创建应用的5个框架
2015/12/05 Javascript
javascript每日必学之封装
2016/02/23 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
把普通对象转换成json格式的对象的简单实例
2016/07/04 Javascript
Angular+Node生成随机数的方法
2017/06/16 Javascript
基于JavaScript实现带数据验证和复选框的表单提交
2017/08/23 Javascript
详解vue中点击空白处隐藏div的实现(用指令实现)
2018/04/19 Javascript
微信小程序当前时间时段选择器插件使用方法详解
2018/12/28 Javascript
elementUi vue el-radio 监听选中变化的实例代码
2019/06/28 Javascript
js闭包的9个使用场景
2020/12/29 Javascript
python开发利器之ulipad的使用实践
2017/03/16 Python
python opencv之SURF算法示例
2018/02/24 Python
Python global全局变量函数详解
2018/09/18 Python
python之线程通过信号pyqtSignal刷新ui的方法
2019/01/11 Python
对python字典过滤条件的实例详解
2019/01/22 Python
Python django框架输入汉字,数字,字符生成二维码实现详解
2019/09/24 Python
python自动识别文本编码格式代码
2019/12/26 Python
pytorch下大型数据集(大型图片)的导入方式
2020/01/08 Python
Python安装依赖(包)模块方法详解
2020/02/14 Python
大学生入党自荐书
2015/03/05 职场文书
教师工作态度自我评价
2015/03/05 职场文书
十二生肖观后感
2015/06/12 职场文书
2016廉洁教育心得体会
2016/01/20 职场文书