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 mb_convert_encoding文字编码的转换函数介绍
Nov 10 PHP
PHP命名空间(Namespace)的使用详解
May 04 PHP
解析php扩展php_curl.dll不加载的解决方法
Jun 26 PHP
解析PHP正则提取或替换img标记属性
Jun 26 PHP
php设计模式之委托模式
Feb 13 PHP
php函数mkdir实现递归创建层级目录
Oct 27 PHP
Yii2――使用数据库操作汇总(增删查改、事务)
Dec 19 PHP
php可变长参数处理函数详解
Feb 22 PHP
php通过pecl方式安装扩展的实例讲解
Feb 02 PHP
php ajax数据传输和响应方法
Aug 21 PHP
CodeIgniter框架实现的整合Smarty引擎DEMO示例
Mar 28 PHP
PHP高并发和大流量解决方案整理
Dec 24 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
The specified CGI application misbehaved by not returning a complete set of HTTP headers
2011/03/31 PHP
PHP 八种基本的数据类型小结
2011/06/01 PHP
浅析PHP递归函数返回值使用方法
2013/02/18 PHP
PHP Filter过滤器全面解析
2016/08/09 PHP
利用Laravel生成Gravatar头像地址的优雅方法
2017/12/30 PHP
nginx 设置多个站跨域
2021/03/09 Servers
JS解决ie6下png透明的方法实例
2013/08/02 Javascript
使用原生js写的一个简单slider
2014/04/29 Javascript
jquery获取img的src值的简单实例
2016/05/17 Javascript
node-http-proxy修改响应结果实例代码
2016/06/06 Javascript
详解Bootstrap各式各样的按钮(推荐)
2016/12/13 Javascript
jQuery实现选项卡功能(两种方法)
2017/03/08 Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
2017/04/14 jQuery
Node.js实现连接mysql数据库功能示例
2017/09/15 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
2019/02/22 Javascript
[07:26]2015国际邀请赛第二日TOP10集锦
2015/08/06 DOTA
Mac中升级Python2.7到Python3.5步骤详解
2017/04/27 Python
Python之多线程爬虫抓取网页图片的示例代码
2018/01/10 Python
Python列表推导式与生成器表达式用法示例
2018/02/08 Python
python对list中的每个元素进行某种操作的方法
2018/06/29 Python
python实现感知机线性分类模型示例代码
2019/06/02 Python
详解numpy矩阵的创建与数据类型
2019/10/18 Python
Python操作Sonqube API获取检测结果并打印过程解析
2019/11/27 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
2019/12/27 Python
pytorch 实现模型不同层设置不同的学习率方式
2020/01/06 Python
html5 拖拽及用 js 实现拖拽功能的示例代码
2020/10/23 HTML / CSS
英国和世界各地预订便宜的酒店:LateRooms.com
2019/05/05 全球购物
Cynthia Rowley官网:全球领先的生活方式品牌
2020/10/27 全球购物
给校长的建议书100字
2014/05/16 职场文书
村干部四风问题整改措施
2014/09/30 职场文书
安全保证书
2015/01/16 职场文书
感恩主题班会教案
2015/08/12 职场文书
2015年乡镇食品安全工作总结
2015/10/22 职场文书
手把手教你从零开始react+antd搭建项目
2021/06/03 Javascript
Vue3.0写自定义指令的简单步骤记录
2021/06/27 Vue.js
tree shaking对打包体积优化及作用
2022/07/07 Java/Android