CI framework Source Code Reading Notes 6 extended Hook. php, cihook. php

Source: Internet
Author: User

CI framework Source Code Reading Notes 6 extended Hook. php, cihook. php
The CI framework allows you to add or change the core functions of the system (such as rewrite cache and output) without modifying the core code of the system ). For example$config['enable_hooks'] = TRUE;By adding a specific Hook, the system can trigger a specific script at a specific time point:

$hook['post_system'] = array(    'class'     => 'frameLog',    'function'  => 'postLog',    'filename'  => 'post_system.php',    'filepath'   => 'hooks',);

The above hook defines a post_system hook for script processing after the final page rendering (the parameter meaning can be referred to later or in the manual, and no more explanation is provided here ).

The problem arises:

Let's look at it step by step.

1. What is a hook?

Baidu encyclopedia defines hooks as follows:

A hook is actually a program segment for message processing. It is called by the system and mounted to the system. When a specific message is sent, the hook program captures the message before it reaches the target window, that is, the hook function gets control of the message first. In this case, the hook function can process (Change) the message, continue to transmit the message without processing it, and forcibly end the message transmission.

From the above definition, we can see the following points:

2. pre-defined hooks in CI

Seven preset hook points are available in CI:

Pre_system:Refers to the hook before the system is loaded.

Pre_controller:The hook before the controller is called. The route and security check has been completed.

Post_controller_constructor:After the controller is instantiated, before any method is called

Post_controller:After the controller is fully running

Display_override:Rewrite display

Cache_override:Rewrite Cache

Post_system:After the final page is sent to the client

3. Implementation of hooks in CI

The core function of the Hook in CI is completed by the Hook component. First, let's look at the class diagram of this component:

 

Where:

Enabled: indicates whether the hook function is enabled.

Hooks: saves the list of enabled hooks in the system.

In_progress: we will see that this flag is used to prevent endless loops caused by mutual calls between hooks.

_ Construct is the constructor of the Hook component, in which _ initialize is called to complete initialization.

_ Call_hook: call _ run_hook to call the specified hook program. We have seen in CodeIgniter. php that _ call_hook is an interface actually provided to external calls.

_ Run_hook: The function used to actually execute the hook Program

Before starting, we first paste the structure of the predefined hook. This structure may run throughout the source code, so we need to know the parameter meaning of this structure.

$ Hook ['xx'] = array ('class' => 'XX', // name of the class called by the hook, which can be blank 'function' => 'XX ', // The Name Of The function called by the hook is 'filename' => 'XX', // the file name of the hook is 'filepath' => 'XX ', // hook directory 'params' => 'xx' // parameters passed to the hook );

1) Hook component Initialization

The _ initialize function is used to initialize the hook component. The main tasks of this function are:

(1) check whether the hook function in the configuration file is enabled. You need to load the Config (configuration management component ):

$CFG =& load_class('Config', 'core');if ($CFG->item('enable_hooks') == FALSE){return;}

(2) load the defined hook list

Similarly, you can set different ENVIRONMENT to enable different hooks. If so, the hooks under ENVRIONMENT are preferentially loaded:

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');}

(3) Hook check. If no hook is set or the format of the hook is incorrect, exit without any processing:

if ( ! isset($hook) OR ! is_array($hook)){return;}

After initialize, Hook: hooks stores the defined hook list:

$this->hooks =& $hook;

2. Hook specified by Call

_ Call_hook is the interface directly called in the main program. The main work of this interface is:

(1). Check whether the hook is enabled and whether the call hook is predefined (if not enabled or the call Hook does not exist, return directly ):

if ( ! $this->enabled OR ! isset($this->hooks[$which])){return FALSE;}

(2) Check whether multiple hooks are enabled for the same hook point. If so, execute the following commands in sequence:

if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0])){foreach ($this->hooks[$which] as $val){$this->_run_hook($val);}}

(3). Otherwise, there is only one hook to execute it.

else{$this->_run_hook($this->hooks[$which]);}

_ Run_hook is the function that actually executes the hook.

3. run the specific hook program.

The _ run_hook function is the actual executor of the hook. The function receives a predefined hook array as a parameter and implements the following:

(1). If the passed parameter is not an array at all (naturally it is not a valid hook), then directly return:

if ( ! is_array($data)){return FALSE;}

(2) Check the hook execution status.

In_progress indicates the execution status of the current hook. This parameter is mainly used to prevent endless loops caused by mutual calls between hooks.

if ($this->in_progress == TRUE){return;}

(3) check the validity of the Hook.

For the sake of convenience, we propose a predefined hook parameter again:

$ Hook ['xx'] = array ('class' => 'XX', // name of the class called by the hook, which can be blank 'function' => 'XX ', // The Name Of The function called by the hook is 'filename' => 'XX', // the file name of the hook is 'filepath' => 'XX ', // hook directory 'params' => 'xx' // parameters passed to the hook );

Among them, class and params are optional parameters, and the other three parameters are required. If this parameter is not provided, the hook program cannot be accurately located and can only be returned directly:

if ( ! isset($data['filepath']) OR ! isset($data['filename'])){return FALSE;}$filepath = APPPATH.$data['filepath'].'/'.$data['filename'];if ( ! file_exists($filepath)){return FALSE;}

(4). At this point, we have basically confirmed the location of the hook program. There are two situations:

A. The class parameter in the predefined hook is null, indicating that a procedural call is used, and function xxx in the hook file is directly executed.

B. if the class parameter is not null and the object-oriented method is provided, the actual hook program is $ class-> $ function. similarly, if neither the class nor the function parameter is set, the hook cannot be executed and the following result is returned:

$ Class = FALSE; $ function = FALSE; $ params = '';/* Get hook class */if (isset ($ data ['class']) AND $ data ['class']! = '') {$ Class = $ data ['class'];}/* Get hook function */if (isset ($ data ['function']) {$ function = $ data ['function'];}/* obtain the passed hook parameter */if (isset ($ data ['params']) {$ params = $ data ['params'];}/* If neither class nor function exists, the hook program cannot be located, directly return */if ($ class === false and $ function === FALSE) {return FALSE ;}

(5). Set the execution flag in_progress and execute the hook in the above two cases:

/* Object-oriented Setting Method */if ($ class! = FALSE) {if (! Class_exists ($ class) {require ($ filepath);} $ HOOK = new $ class; $ HOOK-> $ function ($ params);} else {if (! Function_exists ($ function) {require ($ filepath) ;}$ function ($ params );}

Finally, do not forget to set the in_progress flag to false after the hook is executed, and return the execution success flag:

$this->in_progress = FALSE;return TRUE;

Complete source code of the Hook component:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');class CI_Hooks {/** * Determines wether hooks are enabled * * @var bool */var $enabled= FALSE;/** * List of all hooks set in config/hooks.php * */var $hooks= array();/** * Determines wether hook is in progress, used to prevent infinte loops * */var $in_progress= FALSE;/** * Constructor */function __construct(){$this->_initialize();log_message('debug', "Hooks Class Initialized");}/** * Initialize the Hooks Preferences * * @accessprivate * @returnvoid */function _initialize(){$CFG =& load_class('Config', 'core');// If hooks are not enabled in the config file// there is nothing else to doif ($CFG->item('enable_hooks') == FALSE){return;}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 * * @accessprivate * @paramstringthe hook name * @returnmixed */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 * * @accessprivate * @paramarraythe hook details * @returnbool */function _run_hook($data){if ( ! is_array($data)){return FALSE;}// If the script being called happens to have the same hook call within it a loop can happenif ($this->in_progress == TRUE){return;}if ( ! isset($data['filepath']) OR ! isset($data['filename'])){return FALSE;}$filepath = APPPATH.$data['filepath'].'/'.$data['filename'];if ( ! file_exists($filepath)){return FALSE;}$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;}$this->in_progress = TRUE;// Call the requested class and/or functionif ($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;}}
References

1. http://codeigniter.org.cn/user_guide/general/hooks.html Manual

2. http://itopic.org/codeigniter-hook.html

3. Layout implemented by http://codeigniter.org.cn/forums/thread-4947-1-1.html hooks

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.