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+MYSQL的文章管理系统(一)
Oct 09 PHP
php 模拟POST提交的2种方法详解
Jun 17 PHP
php二分查找二种实现示例
Mar 12 PHP
常用PHP框架功能对照表
Oct 23 PHP
PHP如何通过AJAX方式实现登录功能
Nov 23 PHP
学习php设计模式 php实现策略模式(strategy)
Dec 07 PHP
Laravel中基于Artisan View扩展包创建及删除应用视图文件的方法
Oct 08 PHP
php实现购物车功能(以大苹果购物网为例)
Mar 09 PHP
PHP中Static(静态)关键字功能与用法实例分析
Apr 05 PHP
Thinkphp5 如何隐藏入口文件index.php(URL重写)
Oct 16 PHP
php接口隔离原则实例分析
Nov 11 PHP
php反序列化长度变化尾部字符串逃逸(0CTF-2016-piapiapia)
Feb 15 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中的内存管理问题
2011/08/31 PHP
PHP在引号前面添加反斜杠(PHP去除反斜杠)
2013/09/28 PHP
Yii把CGridView文本框换成下拉框的方法
2014/12/03 PHP
php删除一个路径下的所有文件夹和文件的方法
2018/02/07 PHP
javascript之解决IE下不渲染的bug
2007/06/29 Javascript
LBS blog sql注射漏洞[All version]-官方已有补丁
2007/08/26 Javascript
一个原生的用户等级的进度条
2010/07/03 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
jQuery之过滤元素操作小结
2013/11/30 Javascript
javascript中数组的多种定义方法和常用函数简介
2014/05/09 Javascript
iframe中子父类窗口调用JS的方法及注意事项
2015/08/25 Javascript
jquery编写Tab选项卡滚动导航切换特效
2020/07/17 Javascript
jQuery内容折叠效果插件用法实例分析(附demo源码)
2016/04/28 Javascript
微信小程序 页面跳转传值实现代码
2017/07/27 Javascript
React教程之Props验证的具体用法(Props Validation)
2017/09/04 Javascript
Vue props用法详解(小结)
2018/07/03 Javascript
简单了解node npm cnpm的具体使用方法
2019/02/27 Javascript
详解element-ui设置下拉选择切换必填和非必填
2019/06/17 Javascript
详细介绍解决vue和jsp结合的方法
2020/02/06 Javascript
在vue中配置不同的代理同时访问不同的后台操作
2020/09/11 Javascript
Python实现Windows上气泡提醒效果的方法
2015/06/03 Python
python3.0 模拟用户登录,三次错误锁定的实例
2017/11/02 Python
python取代netcat过程分析
2018/02/10 Python
在python带权重的列表中随机取值的方法
2019/01/23 Python
Flask配置Cors跨域的实现
2019/07/12 Python
django迁移数据库错误问题解决
2019/07/29 Python
Python3基本输入与输出操作实例分析
2020/02/14 Python
opencv之颜色过滤只留下图片中的红色区域操作
2020/06/05 Python
Conforama瑞士:家具、厨房、电器、装饰
2020/09/06 全球购物
四川internet信息高速公路(C#)笔试题
2012/02/29 面试题
标准毕业生自荐信范文
2013/11/04 职场文书
结婚保证书范文
2014/04/29 职场文书
观后感格式
2015/06/19 职场文书
技术转让协议书
2016/03/19 职场文书
导游词之太原天龙山
2020/01/02 职场文书
《风不能把阳光打败》读后感3篇
2020/01/06 职场文书