欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

CodeIgniter框架钩子机制实现方法【hooks类】

程序员文章站 2024-02-07 09:15:58
本文实例讲述了codeigniter框架钩子机制实现方法。分享给大家供大家参考,具体如下: 记得上一次去到喜啦面试,面试官问我一个问题:codeigniter是如何实现钩...

本文实例讲述了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相关内容感兴趣的读者可查看本站专题:《codeigniter入门教程》、《ci(codeigniter)框架进阶教程》、《php优秀开发框架总结》、《thinkphp入门教程》、《thinkphp常用方法总结》、《zend framework框架入门教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总

希望本文所述对大家基于codeigniter框架的php程序设计有所帮助。