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获取当前网址url并替换参数或网址的方法
Jun 06 PHP
整理的一些实用WordPress后台MySQL操作命令
Jan 07 PHP
PHP在不同页面间传递Json数据示例代码
Jun 08 PHP
显示youtube视频缩略图和Vimeo视频缩略图代码分享
Feb 13 PHP
php中simplexml_load_string使用实例分享
Feb 13 PHP
php使用imagick模块实现图片缩放、裁剪、压缩示例
Apr 17 PHP
php实现建立多层级目录的方法
Jul 19 PHP
大家在抢红包,程序员在研究红包算法
Aug 31 PHP
PHP的Yii框架中使用数据库的配置和SQL操作实例教程
Mar 17 PHP
PHP实现15位身份证号转18位的方法分析
Oct 16 PHP
PHP标准库 (SPL)――Countable用法示例
Jun 05 PHP
PHP sdk文档处理常用代码示例解析
Dec 09 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
Adodb的十个实例(清晰版)
2006/12/31 PHP
PHP中if和or运行效率对比
2014/12/12 PHP
JavaScript 设计模式 安全沙箱模式
2010/09/24 Javascript
纯JS实现五子棋游戏兼容各浏览器(附源码)
2013/04/24 Javascript
Javascript无参数和有参数类继承问题解决方法
2015/03/02 Javascript
javascript实现倒计时跳转页面
2016/01/17 Javascript
Bootstrap按钮组件详解
2016/04/26 Javascript
微信开发 微信授权详解
2016/10/21 Javascript
详解vue-cli + webpack 多页面实例应用
2017/04/25 Javascript
iframe高度自适应及隐藏滚动条的实例详解
2017/09/29 Javascript
vue2实现可复用的轮播图carousel组件详解
2017/11/27 Javascript
关于vue-router的那些事儿
2018/05/23 Javascript
JS监听事件的叠加和移除功能
2018/11/19 Javascript
详解webpack引入第三方库的方式以及注意事项
2019/01/15 Javascript
vue弹出框组件封装实例代码
2019/10/31 Javascript
在vue中实现禁止回退上一步,路由不存历史记录
2020/07/22 Javascript
[01:09]DOTA2次级职业联赛 - ishow.HMM战队宣传片
2014/12/01 DOTA
python中nan与inf转为特定数字方法示例
2017/05/11 Python
浅谈python str.format与制表符\t关于中文对齐的细节问题
2019/01/14 Python
解决Pytorch 训练与测试时爆显存(out of memory)的问题
2019/08/20 Python
vue常用指令代码实例总结
2020/03/16 Python
基于python3.7利用Motor来异步读写Mongodb提高效率(推荐)
2020/04/29 Python
HTML5实时语音通话聊天MP3压缩传输3KB每秒
2019/08/28 HTML / CSS
浅析HTML5中header标签的用法
2016/06/24 HTML / CSS
韩国11街:11STREET
2018/03/27 全球购物
缓解脚、腿和背部疼痛:Z-CoiL鞋
2019/03/12 全球购物
俄罗斯最大的香水和化妆品网上商店:Randewoo
2020/11/05 全球购物
食堂员工工作职责
2013/12/18 职场文书
幼儿园义卖活动方案
2014/01/17 职场文书
《月迹》教学反思
2014/02/19 职场文书
总经理的岗位职责
2014/02/23 职场文书
群众路线教育实践活动批评与自我批评
2014/09/15 职场文书
致百米运动员广播稿5篇
2014/10/13 职场文书
小孩不笨观后感
2015/06/03 职场文书
《七律·长征》教学反思
2016/02/16 职场文书
Spring Boot项目如何优雅实现Excel导入与导出功能
2022/06/10 Java/Android