CI Framework Source Reading notes 6 extension hooks hook.php

Source: Internet
Author: User
Tags codeigniter

The CI framework allows you to add or change the core functions of the system (such as rewriting the cache, output, etc.) without modifying the core code of the system. For example, when the system opens the hook (in config.php $config[‘enable_hooks‘] = TRUE; ), by adding a specific hook, you can have the system trigger a specific script at a specific moment:
$hook Array (    ' class '     = ' framelog ',    ' function '  = ' postlog ',    ' filename '  = ' post_ ') System.php ',    ' filepath '   = ' hooks ',);

The above hooks define a post_system hook for script processing after the final page rendering (the meaning of the parameters can be referred to later or manual, there is no more explanation for the moment).

So here's the question:

    1. What is a hook?
    2. What are the hooks supported in CI?
    3. How is the hook implemented in CI?

We take a step-by-step look.

1.What is a hook?

Baidu Encyclopedia on the definition of hooks is:

A hook is actually a program segment that processes messages, and it is put into the system by a system call. Whenever a particular message is issued, the hook program captures the message before it reaches the destination window, i.e. the hook function gets control first. At this point the hook function can process (change) the message, or you can continue to pass the message without processing, and you can force the end of the message delivery.

From the above definition we can see a few points:

    1. A hook is an event-driven pattern whose core is naturally the event (Pre_system,pre_controller in CI is a specific event).
    2. Since it is event driven, it is necessary to include the two most important steps: (1), Event registration . In the case of hooks, the hook hooks are mounted. (2). event triggering . Call a specific hook at a specific point in time to perform the corresponding hook procedure.
    3. Since it is event driven, you should also support multiple registration events for a unified hook point.
    4. After starting the hook hook, the process of the program may change, and the hooks may have the possibility of mutual invocation, if handled improperly, there is the possibility of a dead loop. At the same time, the activation of hooks makes the program complicated to some extent and difficult to debug.
2. Pre-defined hooks in CI

There are 7 preset hook-up points available in CI, namely:

Pre_system: refers to the hook in the pre-loading system

Pre_controller: call controller before the hook, Routing and security check is complete

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

Post_controller: After the controller is fully operational

display_override: rewrite display

cache_override: overriding the cache

Post_system: After the final page is sent to the client

3. Implementation of hooks in CI

The core function of a hook in CI is done by the hook component, which first looks at the class diagram of the component:

which

enabled: The flag of whether the hook function is turned on.

Hooks : Save the list of hooks enabled in the system

in_progress: Then we will see that this flag bit is used to prevent the loop of loops caused by calls to each other between hooks.

_construct is the constructor of the hook component, which calls the _initialize to complete the initialization work

_call_hook: Calls _run_hook to call the specified hook program. As we have seen in the previous codeigniter.php, _call_hook is the interface actually provided to external calls.

_run_hook: A function that actually executes the hook program

Before we start, we'll put together the structure of the predefined hooks. This structure may be consistent throughout the source code, so it is necessary to know the meaning of the parameters of the structure.

$hook Array (         The class name of the ' class '// hook call, can be null    ' function '  = ' xx ',//  The function name of the hook call    ' filename '  = ' xx ',// The name of the hook '    filepath '   = ' xx ', // Directory of hooks    ' Params '   = ' xx '/// parameters passed to the hook );

1). Hook Component Initialization

The _initialize function is used for the initialization of the hook component, which mainly accomplishes the following tasks:

(1) Check whether the hook function is enabled in the configuration file, which requires the config (Configuration management component) to be loaded:

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

(2) Load a list of defined hooks

Similarly, you can set different environment to enable different hooks, and if so, load the hooks under envrionment First:

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) Check the hook. If no hooks are set, or if the hook format is incorrect, no processing is done and exit directly:

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

After initialize, the list of hooks that have already been defined is stored in hook::hooks:

$this->hooks =& $hook;

2. Call-Specified hooks

_call_hook is the interface that is called directly in the main program. The main work of this interface is:

(1). Check that the hook is enabled and that the call's hook is predefined (if it is not enabled or the call's hook does not exist, it is returned directly):

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

(2). Check if multiple hooks are enabled for the same hook point, and if so, do it in turn:

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 that executes it

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

_run_hook is the function that actually executes the hook.

3. Run performs a specific hook procedure

The _run_hook function is the actual performer of the hook, which receives a pre-defined hook array as a parameter, implemented as follows:

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

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

(2). Check the hook execution status.

The in_progress is used to flag the execution state of the current hook. The main function of this parameter is to prevent the loop of loops caused by mutual calls between hooks.

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

(3). Check the legality of hooks.

To facilitate the narration, we again present a predefined hook for the required parameters:

$hook Array (         The class name of the ' class '// hook call, can be null    ' function '  = ' xx ',//  The function name of the hook call    ' filename '  = ' xx ',// The name of the hook '    filepath '   = ' xx ', // Directory of hooks    ' Params '   = ' xx '/// parameters passed to the hook );

Where class and params are optional parameters, the other 3 parameters are required parameters, if not provided, it can not be accurately located to the hook program, only directly return:

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

(4). Here, there is a basic confirmation of the location of the hook program, there are two situations:

A. The class parameter in the predefined hooks is NULL, indicating that the procedure is used, and the function xxx in the hook file is executed directly

B. The class parameter is not NULL, provided is an object-oriented approach, the actual hook program is $class-> $function. Similarly, if neither the class nor the function parameter is set, the hook cannot be executed and returned directly:

$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 '];} /* Get the passed hook parameter */if (isset ($data [' params '])) {$params = $data [' params '];} /* If both class and function do not exist, the hook program cannot be located, return */if directly ($class = = = False and $function = = = False) {return false;}

(5). Set the execution flag in_progress, and perform the hooks in both cases:

/* Object-oriented setting */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, don't forget to set the identity bit in_progress to false after the hook executes, and return the flag to execute successfully:

$this->in_progress = False;return TRUE;

The complete source of the hook component:

<?php if (! defined (' BasePath ')) exit (' No Direct script access allowed '); class Ci_hooks {/** * determines wether hook S is 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 (' C Onfig ', ' core ');//If hooks is not enabled in the config file//there was nothing else to Doif ($CFG->item (' Enable_hook s ') = = 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_h Ook ($data) {if (! Is_array ($data)) {return FALSE;} If the script being called happens to has the same hook call within it a loop can happenif ($this->in_progress = = T RUE) {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;}}
Reference documents

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

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

3. Layout of the http://codeigniter.org.cn/forums/thread-4947-1-1.html hook implementation

CI Framework Source Reading notes 6 extension hooks hook.php

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.