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中的Class的几点个人看法
Oct 09 PHP
PHP中一个控制字符串输出的函数
Oct 09 PHP
PHP输入流php://input介绍
Sep 18 PHP
CentOS 6.2使用yum安装LAMP以及phpMyadmin详解
Jun 17 PHP
php文件服务实现虚拟挂载其他目录示例
Apr 17 PHP
php curl 获取https请求的2种方法
Apr 27 PHP
php实现的递归提成方案实例
Nov 14 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
Dec 19 PHP
PHP使用file_get_content设置头信息的方法
Feb 14 PHP
PHP微信分享开发详解
Jan 14 PHP
PDO实现学生管理系统
Mar 21 PHP
PHP程序员简单的开展服务治理架构操作详解(一)
May 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知识收集
2012/08/20 PHP
Thinkphp调用Image类生成缩略图的方法
2015/03/07 PHP
php源码分析之DZX1.5字符串截断函数cutstr用法
2015/06/17 PHP
PHP对象链式操作实现原理分析
2016/10/09 PHP
PHP上传图片时判断上传文件是否为可用图片的方法
2016/10/20 PHP
浅谈php数组array_change_key_case() 函数和array_chunk()函数
2016/10/22 PHP
js转义字符介绍
2013/11/05 Javascript
ActiveX控件与Javascript之间的交互示例
2014/06/04 Javascript
javascript中setTimeout和setInterval的unref()和ref()用法示例
2014/11/26 Javascript
js实现Form栏显示全格式时间时钟效果代码
2015/08/19 Javascript
JavaScript引用类型和基本类型详解
2016/01/06 Javascript
JavaScript 中 avalon绑定属性总结
2016/10/19 Javascript
Vue.js 中的 $watch使用方法
2017/05/25 Javascript
js 两数组去除重复数值的实例
2017/12/06 Javascript
vue 实现全选全不选的示例代码
2018/03/29 Javascript
Angular父组件调用子组件的方法
2018/04/02 Javascript
详解redis在nodejs中的应用
2018/05/02 NodeJs
微信小程序下拉菜单效果的实例代码
2019/05/14 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
2019/07/05 Javascript
[00:44]TI7不朽珍藏III——军团指挥官不朽展示
2017/07/15 DOTA
python使用PIL模块实现给图片打水印的方法
2015/05/22 Python
Python中optparser库用法实例详解
2018/01/26 Python
浅谈python实现Google翻译PDF,解决换行的问题
2018/11/28 Python
利用python实现简易版的贪吃蛇游戏(面向python小白)
2018/12/30 Python
用xpath获取指定标签下的所有text的实例
2019/01/02 Python
python两个_多个字典合并相加的实例代码
2019/12/26 Python
python统计字符串中字母出现次数代码实例
2020/03/02 Python
python“静态”变量、实例变量与本地变量的声明示例
2020/11/13 Python
Html5元素及基本语法详解
2016/08/02 HTML / CSS
HTML5超文本标记语言的实现方法
2020/09/24 HTML / CSS
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
项目经理任命书内容
2014/06/06 职场文书
2014年保安个人工作总结
2014/11/13 职场文书
Mysql 如何批量插入数据
2021/04/06 MySQL
自己搭建resnet18网络并加载torchvision自带权重的操作
2021/05/13 Python
《帝国时代4》赛季预告 新增内容编译器可创造地图
2022/04/03 其他游戏