This article mainly introduces the research on the working principle of the PHP CodeIgniter framework. This article first analyzes its workflow, and then summarizes its Working principle, friends in need can refer to it
CodeIgniter (hereinafter referred to as CI, official website and Chinese website) is a popular PHP framework. It is small but powerful, simple and lightweight and has good scalability. It is also quite popular in China. On the other hand, CI has not kept pace with the times and does not support some features after PHP5.3, making it relatively more suitable for older projects. Even so, CI is still an excellent framework, and it has a smaller core, elegant source code, and is suitable for learning.
CI is easy to use and can easily develop web applications. Let’s first take a look at the CI workflow diagram (the content here is quoted from http://codeigniter.org.cn/user_guide/overview/appflow.html)
,
1.index.php serves as the front-end controller to initialize the basic resources required to run CodeIgniter.
2.Router checks the HTTP request to determine who should handle the request.
3. If the cache file exists, it will bypass the usual system execution sequence and be sent directly to the browser.
4. Security. HTTP requests and any user-submitted data will be filtered before the Application Controller is loaded.
5. The Controller loads models, core libraries, helper functions, and any other resources needed to handle specific requests.
6. The final view renders the content sent to the web browser. If caching is turned on, the view is cached first so it will be available for future requests.
The above gives a general process. So when you see the page rendered in the browser, how exactly does the program work internally?
The following is a list of the main files loaded by the CI framework in order of execution, and a brief introduction to their functions:
01. index.php
Define the usage environment (ENVIRONMENT), framework path (system_path, BASEPATH), application directory (application_folder), application path (APPPATH), etc., and load (require) the CI core file
02. BASEPATH/core/CodeIgniter.php (ps. Actually BASEPATH contains the final file separator '/', the additional '/' is added here for clearer display)
The system initialization file, the core part of the entire framework, loads a series of base classes here and executes this request
03. BASEPATH/core/Common.php
The common file contains a series of basic and public functions for global use, such as load_class(), get_config(), etc.
04. BASEPATH/core/Benchmark
This is a benchmark class that by default marks the execution points of each stage of the application to obtain its execution time. Also allows you to define monitoring points yourself.
05. BASEPATH/core/Hooks.php
CI_Hooks is a hook class, which is the core of the framework expansion. It can insert hook points at various stages allowed by the program and execute your customized classes, functions, etc.
06. BASEPATH/core/Config.php
Configuration file management class, loading, reading or setting configuration
07. BASEPATH/core/URI.php, BASEPATH/core/Router.php
The URI class helps you parse the requested URI and provides a set of functions to split the URI for use by the Router class
08. BASEPATH/core/Router.php
The routing class distributes user requests to the specified processing function (usually an action function in a Controller instance) through the requested URI and the user-configured route (APPPATH/config/routes.php)
09. BASEPATH/core/Output.php, BASEPATH/core/Input.php
The input class handles the input parameters of the request and provides a safe way to obtain them. The output class sends out the final execution results, and is also responsible for the caching function
10. BASEPATH/core/Controller.php
The controller base class uses singleton mode to provide instances to the outside world and is the heart of the entire application. It is a Super Object. Classes loaded in the application can become member variables of the controller. This is very important and will be discussed later.
11. APPPATH/controllers/$RTR->fetch_directory().$RTR->fetch_class().'.php'
Through the routing function, get the controller name and instantiate the real controller class (subclass)
12. BASEPATH/core/Loader.php
CI_Loader is used to load various class libraries, models, views, databases, files, etc. in the application and set them as member variables of the controller
13. call_user_func_array call processing function
Through routing, the action function name is obtained, and the Controller->action() function is called to process the application logic. The actual business processing logic is written in the action function
14. $OUT->_display() outputs the content
The above is the most basic processing flow of the entire application. The following selects the core content code and explains it to enhance the understanding of CI:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
//*BASEPATH/system/core/Common.php //引导文件中Benchmark,Hooks,Config等都是通过这个函数进行加载的 function &load_class($class, $directory = 'libraries', $prefix = 'CI_') { //记录加载过的类 static $_classes = array();
// 已经加载过,直接读取并返回 if (isset($_classes[$class])) { return $_classes[$class]; }
$name = FALSE;
// 在指定目录寻找要加载的类 foreach (array(APPPATH, BASEPATH) as $path) { if (file_exists($path.$directory.'/'.$class.'.php')) { $name = $prefix.$class;
if (class_exists($name) === FALSE) { require($path.$directory.'/'.$class.'.php'); }
break; } }
// Not found if ($name === FALSE) { exit('Unable to locate the specified class: '.$class.'.php'); }
//Trace and record the class just loaded, the is_loaded() function is below is_loaded($class);
$_classes[$class] = new $name(); return $_classes[$class]; } //Record loaded classes. The function returns all loaded classes function &is_loaded($class = '') { static $_is_loaded = array();
if ($class != '') { $_is_loaded[strtolower($class)] = $class; }
return $_is_loaded; }
//*BASEPATH/system/core/Controller.php class CI_Controller {
private static $instance;
public function __construct() { self::$instance =& $this;
// Initialize all class objects in the boot file (CodeIgniter.php) (i.e. steps 4, 5, 6, 7, 8, 9, etc. just now), //Registering as a member variable of the controller class makes this controller a super object foreach (is_loaded() as $var => $class) { $this->$var =& load_class($class); } //Load the Loader object, and then use the Loader object to load a series of resources in the program $this->load =& load_class('Loader', 'core');
$this->load->initialize();
log_message('debug', "Controller Class Initialized"); }
//This function provides a single instance of the controller to the outside world public static function &get_instance() { return self::$instance; } }
//*BASEPATH/system/core/CodeIgniter.php // Load the base controller class require BASEPATH.'core/Controller.php';
//Through this global function, the instance of the controller is obtained, and the super object is obtained, //It means that by calling this function elsewhere in the program, you can gain control of the entire framework function &get_instance() { return CI_Controller::get_instance(); }
//Load the corresponding controller class // Note: Router class will automatically use router->_validate_request() to verify the controller path 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');
$class = $RTR->fetch_class(); //Controller class name $method = $RTR->fetch_method(); //action name
//....
//Call the requested function // The segments in the uri except class/function will also be passed to the called function call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
//Output the final content to the browser if ($EXT->_call_hook('display_override') === FALSE) { $OUT->_display(); }
//*BASEPATH/system/core/Loader.php //Look at an example of Loader class loading model. Only part of the code is listed here public function model($model, $name = '', $db_conn = FALSE) { $CI =& get_instance(); if (isset($CI->$name)) { show_error('The model name you are loading is the name of a resource that is already being used: '.$name); }
$model = strtolower($model);
//Match according to the path of the model class in turn, and load it if found foreach ($this->_ci_model_paths as $mod_path) { if ( ! file_exists($mod_path.'models/'.$path.$model.'.php')) { continue; }
if ($db_conn !== FALSE AND ! class_exists('CI_DB')) { if ($db_conn === TRUE) { $db_conn = ''; }
$CI->load->database($db_conn, FALSE, TRUE); }
if ( ! class_exists('CI_Model')) { load_class('Model', 'core'); }
require_once($mod_path.'models/'.$path.$model.'.php');
$model = ucfirst($model);
//Here the model object is still registered as a member variable of the controller class. Loader will also do this when loading other resources $CI->$name = new $model();
$this->_ci_models[] = $name; return; }
// couldn't find the model show_error('Unable to locate the model you have specified: '.$model); }
//*BASEPATH/system/core/Model.php //__get() is a magic method that is called when reading the value of an undefined variable //The following is an implementation of the __get() function by the Model base class, so that it can be read in the Model class as directly in the controller class (such as $this->var) Variable of function __get($key) { $CI =& get_instance(); return $CI->$key; |