CI framework Source Code Reading Notes 4 guide file CodeIgniter. php

Source: Internet
Author: User
Tags constant definition pconnect
CI framework source code reading Note 4 guide file CodeIgniter. php is here, and finally enters the core of the CI framework. Since it is a "pilot" file, it is to guide user requests, parameters, and so on, so that user requests and data streams are separated by the correct line. For example, the user's request url:

   http://you.host.com/usr/reg

The boot file is actually handed over to the reg method of the UsrController controller in the Application for processing. In this process, what does CodeIgniter. php do? Let's look at it step by step.

1. import predefined constants and framework environment initialization

Previous Blog (CI framework source code reading Note 2 all entries index. php), we can see that Index. the PHP file has defined and checked the ENVIRONMENT, application, and system of the framework.

(1). load the predefined constant Constants.

If the environment is defined and the predefined constant file for the environment exists, the constant definition file of the environment is preferentially loaded; otherwise, the constant definition file under the config directory is loaded:

if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php')) { require(APPPATH.'config/'.ENVIRONMENT.'/constants.php'); } else{ require(APPPATH.'config/constants.php'); }

The reason for this is that we have already introduced how to quickly switch the environment and parameters without changing the core code of the application.

(2) set the custom error handling function.

Here is the _ exception_handler function, the definition and interpretation of this function see the previous blog (http://www.cnblogs.com/ohmygirl/p/CIRead-3.html ). Reference a sentence in the manual again to remind everyone that the following errors cannot be handled by user-defined functions:E_ERROR,E_PARSE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING, AndSet_error_handler ()The majority generated in the file where the function is locatedE_STRICT.

(3) Check whether the core class is extended

if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '') { get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix'])); }

$ Assign_to_config should be defined in the Index of the entry file. php configuration array. generally, the name of the CI core component starts with "CI _". if you have changed or extended the CI core component, you should use different subclass_prefix prefixes, such as MY _, in this case, you should specify the prefix name of your extension core through $ assign_to_config ['subclass _ prefix'] to facilitate the CI Loader component to load the class, or the file cannot be found. In addition, the default subclass_prefix configuration item is in APPPATH/Config/config. in the php configuration file, this code also tells us that index. the subclass_prefix in the PHP file has a higher priority (that is, if subclass_prefix and index are both set. the configuration items in php overwrite the configuration file Config. php configuration ).

By now, the initialization of the basic environment configuration of the CI framework is complete. Next, CodeIgniter will use a series of components to complete more requirements.

2. load core components

Generally, different functions in the CI framework are implemented by different components (for example, the Log component is mainly used to record logs, and the Input component is used to process user GET, POST, and other data) this modular approach reduces coupling between components and facilitates expansion. The main core components in CI are as follows:

Where:

BM: BenchMark is a BenchMark component of CI. it is mainly used to mark various time points, record memory usage and other parameters, facilitating performance testing and tracking.

EXT: The CI extension component, which has been introduced earlier, is used to change or add the core running functions of the system without changing the CI core. Hook hooks allow you to add custom functions and tracking to various hook points running in the system, such as pre_system, pre_controller, and post_controller. All the following $ EXT-> _ call_hook ("xxx"); programs are called specific hook points (if any ).

CFG: Config configuration management component. It is mainly used to load configuration files, obtain and set configuration items.

UNI: Used to support UTF-8 character set processing. Other components, such as the INPUT component, must be supported by the component.

URI: Parse URI (Uniform Rescource Identifier) parameters. this component is closely related to the RTR component. (It seems that URI and Router are good friends everywhere ).

RTR: Routing component. The data flow direction (route) is determined through parameter parsing of the URI component ).

OUT: The final output management component manages the final output of CI (customs ).

SEC: Security processing component. After all, security issues are always a big problem.

Taking the BM component as an example, the core components are loaded in the following ways:

$BM =& load_class('Benchmark', 'core');

The load_class function is called to obtain the corresponding components in the core directory. (For the implementation and specific introduction of load_class, see the previous blog: CI framework source code reading Note 3 global function Common. php)

The functions and implementations of each component are analyzed in detail. here we only need to know the basic functions of the component.

3. set the route.

The call is very simple. there is only one sentence:

$RTR->_set_routing();

Call the _ set_routing () function of the Router component to set the route. for the specific implementation details, we will not care about it for the moment (the subsequent sections will be described in detail). we only need to know, through _ set_routing, we can obtain the actual request's Controller, URI's segment parameter segment, and other information.

It is worth noting that CI is allowed in index. configure routing in php and overwrite the default routing settings (for example, multiple applications that share the CI installation directory may have different routing ):

if (isset($routing)) { $RTR->_set_overrides($routing); }

After the route is set, you can obtain the directories, classes, and methods through the following components: fetch_diretory (), fetch_class (), and fetch_method.

4. check cache

In this step, CI will first check whether there is a cache_override hook (no configuration by default, that is, FALSE is returned). if not registered, call the _ display_cache method to output the cache (This statement is not accurate. it should be accurate. if there is a corresponding cache, it outputs the cache and exits the program directly; otherwise, FALSE is returned, here, we will not consider implementation details for the moment ):

if ($EXT->_call_hook('cache_override') === FALSE) { if ($OUT->_display_cache($CFG, $URI) == TRUE) { exit; } }

5. instantiate the controller for security verification and actual request processing.

This shows that the previous cache is not hit (in fact, any page should first go to this step before the cache is set, and then the access check cache will hit ). In this step, the require Controller base class and the extended Controller class (if any) and the actual application Controller class are used:

require BASEPATH.'core/Controller.php'; if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php')) { require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'; } if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php')) { show_error('xxx'); } include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'); 

As we have said before, after the Router component _ set_routing, you can obtain the requested file directories, controllers, and methods through fetch_directory (), fetch_class (), and fetch_method.

Now we verify the request controller and method. let's take a look at the main verification of CI:

if ( ! class_exists($class) OR strncmp($method, '_', 1) == 0 OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller'))) )

Here, I will briefly explain the situations that CI deems illegal:

(1). the requested class does not exist :! Class_exists ($ class)

(2 ). the request method starts with "_" (considered as a private method, because php does not support private or public access in the first place ): strncmp ($ method, '_', 1) = 0

(3) methods in the base class CI_Controller cannot be directly accessed: in_array (strtolower ($ method), array_map ('strtolower ', get_class_methods ('ci _ controller '))

If the request conditions meet any of the preceding three conditions, the request is considered invalid (or cannot be located ), therefore, it will be directed to the 404 page by CI (it is worth noting that if 404_override is set and the 404_override class exists, it will not directly call show_404 and exit, it will be instantiated like normal access: $ CI = new $ class ();)

Here, the CI Controller is finally loaded (tired ). However, it is slow and there are still many things to do:

(1). check _ remap.

  _ Remap is similar to CI rewrite. it can locate your request to another location. This method should be defined in your application controller:

public function _remap($method){ $this->index(); }

Now, all requests are directed to the index () of the changed controller. If _ remap does not exist, call the $ method of the actual controller:

call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));

(2). final output

$ This-> load-> view () is not directly output, but stored in the cache. After $ Out-> _ display, the cache is set and the final Output is made (for details, see Output. php and Loader. php)

(3) If a database is used, you must disable the database connection:

if (class_exists('CI_DB') AND isset($CI->db)) { $CI->db->close(); }

Note: If pconnect is enabled in Config/database. php, the established connection is a persistent connection, which will not be closed. Therefore, use pconnect with caution.

Up to now, the core process of CI has finally been completed (although there are still many details, but in any case, the branches of the tree have been completed, and the details of the leaves can be added slowly ). Before finishing this article, let's sort out the core execution process of CI:

Looking back at the official flowchart we quoted earlier, is it basically the same:

Finally, paste the source code of the entire file:

 $ Assign_to_config ['subclass _ prefix']);}/** Set a liberal script execution time limit * // if (function_exists ("set_time_limit ")&&@! Ini_get ("safe_mode") if (function_exists ("set_time_limit") = true and @ ini_get ("safe_mode") = 0) {@ set_time_limit (300 );} $ BM = & load_class ('benchmark', 'core'); $ BM-> mark ('total _ execution_time_start '); $ BM-> mark ('loading _ time: _ base_classes_start ');/** Instantiate the hooks class */$ EXT = & load_class ('hooks', 'core');/** Is there a "pre_system" hook? */$ EXT-> _ call_hook ('pre _ system');/** Instantiate the config class */$ CFG = & load_class ('config', 'core '); // Do we have any manually set config items in the index. php file? If (isset ($ assign_to_config) {$ CFG-> _ assign_to_config ($ assign_to_config);}/*** Instantiate the UTF-8 class */$ UNI = & load_class ('utf8 ', 'core');/** ------------------------------------------------------ * Instantiate the URI class * optional */$ URI = & load_class ('uri ', 'core '); /** Instantiate the routing class and set the routing */$ RTR = & load _ Class ('router ', 'core'); $ RTR-> _ set_routing (); // Set any routing overrides that may exist in the main index file if (isset ($ routing) {$ RTR-> _ set_overrides ($ routing );} /** Instantiate the output class */$ OUT = & load_class ('output', 'core');/** Is there a valid cache file? If so, we're done... */if ($ EXT-> _ call_hook ('cache _ override') === FALSE) {if ($ OUT-> _ display_cache ($ CFG, $ URI) = TRUE) {exit ;}}/** Load the security class for xss and csrf support */$ SEC = & load_class ('security', 'core '); /** Load the Input class and sanitize globals */$ IN = & load_class ('input', 'core '); /** Load the Language class */$ LANG = & load_class ('Lang ', 'core');/** Load the app Controller and local controller * // Load the base controller class require BASEPATH. 'core/Controller. php '; function & get_instance () {return CI_Controller: get_instance ();} if (file_exists (APPPATH. 'core /'. $ CFG-> config ['subclass _ prefix']. 'controller. php ') {require APPPATH. 'core /'. $ CFG-> config ['subclass _ prefix']. 'controller. php ';} if (! File_exists (APPPATH. 'controllers /'. $ RTR-> fetch_directory (). $ RTR-> fetch_class (). '. php ') {show_error ('unable to load your default controller. please make sure the controller specified in your Routes. php file is valid. ');} include (APPPATH. 'controllers /'. $ RTR-> fetch_directory (). $ RTR-> fetch_class (). '. php '); $ BM-> mark ('loading _ time: _ base_classes_end');/** Security check */$ class = $ RTR-> fetch_class (); $ Method = $ RTR-> fetch_method (); if (! Class_exists ($ class) OR strncmp ($ method, '_', 1) = 0 OR in_array (strtolower ($ method), array_map ('strtolower ', get_class_methods ('ci _ controller') {if (! Empty ($ RTR-> routes ['1970 _ override']) {$ x = explode ('/', $ RTR-> routes ['1970 _ override']); $ class = $ x [0]; $ method = (isset ($ x [1])? $ X [1]: 'index'); if (! Class_exists ($ class) {if (! File_exists (APPPATH. 'controllers /'. $ class. '. php ') {show_404 ("{$ class}/{$ method}");} include_once (APPPATH. 'controllers /'. $ class. '. php ') ;}} else {show_404 ("{$ class}/{$ method}") ;}}/** Is there a "pre_controller" hook? */$ EXT-> _ call_hook ('pre _ controller '); /** Instantiate the requested controller * // Mark a start point so we can benchmark the controller $ BM-> mark ('Controller _ execution_time _('. $ class. '/'. $ method. ') _ start'); $ CI = new $ class ();/** Is there a "post_controller_constructor" hook? */$ EXT-> _ call_hook ('post _ controller_constructor ');/** Call the requested method * // Is there a "remap" function? If so, we call it instead if (method_exists ($ CI, '_ remap') {$ CI-> _ remap ($ method, array_slice ($ URI-> rsegments, 2);} else {if (! In_array (strtolower ($ method), array_map ('strtolower ', get_class_methods ($ CI) {if (! Empty ($ RTR-> routes ['1970 _ override']) {$ x = explode ('/', $ RTR-> routes ['1970 _ override']); $ class = $ x [0]; $ method = (isset ($ x [1])? $ X [1]: 'index'); if (! Class_exists ($ class) {if (! File_exists (APPPATH. 'controllers /'. $ class. '. php ') {show_404 ("{$ class}/{$ method}");} include_once (APPPATH. 'controllers /'. $ class. '. php '); unset ($ CI); $ CI = new $ class () ;}} else {show_404 ("{$ class}/{$ method }");}} call_user_func_array (array (& $ CI, $ method), array_slice ($ URI-> rsegments, 2 ));} // Mark a benchmark end point $ BM-> mark ('Controller _ execution_time _('. $ class. '/'. $ method. ') _ end ');/ ** Is there a "post_controller" hook? */$ EXT-> _ call_hook ('post _ controller '); /** Send the final rendered output to the browser */if ($ EXT-> _ call_hook ('display _ override') = FALSE) {$ OUT-> _ display ();}/** Is there a "post_system" hook? */$ EXT-> _ call_hook ('post _ system');/** Close the DB connection if one exists */if (class_exists ('ci _ db ') AND isset ($ CI-> db) {$ CI-> db-> close ();}/* End of file CodeIgniter. php */

Due to the rush in writing, errors may inevitably occur. You are welcome to point out at any time and communicate with each other.

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.