CI框架3.0系统文件CodeIgniter分析
- 1.加载常量文件
- 2.加载系统常用函数
- 3.安全的设置系统全局变量
- 4.设置自定义的错误、异常、停止函数
- 5.自动加载扩展裤
- 6.加载程序运行时间以及内存的函数
- 7.加载系统钩子
- 8.调用系统程序开始的钩子
- 9.加载config参数
- 10.设置系统字符集
- 11.加载php版本不兼容的函数
- 12.加载字符集类
- 13.加载请求地址解析类
- 14.加载路由类
- 15.加载输出类
- 16.输出缓存
- 17.加载过滤类
- 18.加载输入类
- 19.加载语言类
- 20.加载核心控制器类
- 21.设置一个外部可调用框架app的类
- 22.加载自定义替换核心控制器类库
- 23.基础类加载完成记录
- 24.如果类不存在或者方法不存在则提示404
- 25.执行per_controller 钩子
- 26.设置控制器执行时间开始记录
- 27.创建控制器对象
- 28.执行控制器初始化钩子
- 29.调用回调函数,执行路由
- 30.设置控制器执行完成计时
- 31.执行控制器执行钩子
- 32.显示执行后的需要显示的内容
- 33.执行系统执行完成的钩子
- 34.程序运行分析
1.加载常量文件
如果有ENVIRONMENT模式的常量配置则先加载ENVIRONMENT常量配置
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
{
require_once(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
}
require_once(APPPATH.'config/constants.php');
2.加载系统常用函数
require_once(BASEPATH.'core/Common.php');
3.安全的设置系统全局变量
1.判断当前php版本是否为5.4
2.设置自动文件读取和数据库读取的转移为false
3.判断php.ini是否设置了get,post等传递过来的值为全局变量(全局变量容易造成变量混乱)
4.variables_order这个是php.ini设置的启动哪些全局变量,
设置系统变量
ps:至于为什么是php5.4,可能是php5.4默认配置文件是开启自动转移和自动设置为全局变量
if ( ! is_php('5.4'))
{
ini_set('magic_quotes_runtime', 0);
if ((bool) ini_get('register_globals'))
{
$_protected = array(
'_SERVER',
'_GET',
'_POST',
'_FILES',
'_REQUEST',
'_SESSION',
'_ENV',
'_COOKIE',
'GLOBALS',
'HTTP_RAW_POST_DATA',
'system_path',
'application_folder',
'view_folder',
'_protected',
'_registered'
);
$_registered = ini_get('variables_order');
foreach (array('E' => '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal)
{
if (strpos($_registered, $key) === FALSE)
{
continue;
}
foreach (array_keys($$superglobal) as $var)
{
if (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE))
{
$GLOBALS[$var] = NULL;
}
}
}
}
}
4.设置自定义的错误、异常、停止函数
set_error_handler('_error_handler');
set_exception_handler('_exception_handler');
register_shutdown_function('_shutdown_handler');
5.自动加载扩展裤
if ($composer_autoload = config_item('composer_autoload'))
{
if ($composer_autoload === TRUE)
{
file_exists(APPPATH.'vendor/autoload.php')
? require_once(APPPATH.'vendor/autoload.php')
: log_message('error', '$config[\'composer_autoload\'] is set to TRUE but '.APPPATH.'vendor/autoload.php was not found.');
}
elseif (file_exists($composer_autoload))
{
require_once($composer_autoload);
}
else
{
log_message('error', 'Could not find the specified $config[\'composer_autoload\'] path: '.$composer_autoload);
}
}
6.加载程序运行时间以及内存的函数
$BM =& load_class('Benchmark', 'core');
$BM->mark('total_execution_time_start');
$BM->mark('loading_time:_base_classes_start');
7.加载系统钩子
钩子类似于程序的生命周期中调用的函数
$EXT =& load_class('Hooks', 'core');
8.调用系统程序开始的钩子
$EXT->call_hook('pre_system');
9.加载config参数
先加载系统自带的config文件里的参数,再加载index.php中自己定义的额外参数
$CFG =& load_class('Config', 'core');
// Do we have any manually set config items in the index.php file?
if (isset($assign_to_config) && is_array($assign_to_config))
{
foreach ($assign_to_config as $key => $value)
{
$CFG->set_item($key, $value);
}
}
10.设置系统字符集
$charset = strtoupper(config_item('charset'));
ini_set('default_charset', $charset);
11.加载php版本不兼容的函数
require_once(BASEPATH.'core/compat/mbstring.php');
require_once(BASEPATH.'core/compat/hash.php');
require_once(BASEPATH.'core/compat/password.php');
require_once(BASEPATH.'core/compat/standard.php');
12.加载字符集类
$UNI =& load_class('Utf8', 'core');
13.加载请求地址解析类
$URI =& load_class('URI', 'core');
14.加载路由类
$RTR =& load_class('Router', 'core', isset($routing) ? $routing : NULL);
15.加载输出类
$OUT =& load_class('Output', 'core');
16.输出缓存
如果检测到该请求有缓存,则直接输出缓存
if ($EXT->call_hook('cache_override') === FALSE && $OUT->_display_cache($CFG, $URI) === TRUE)
{
exit;
}
17.加载过滤类
过滤xss、csrf等
$SEC =& load_class('Security', 'core');
18.加载输入类
$IN =& load_class('Input', 'core');
19.加载语言类
$LANG =& load_class('Lang', 'core');
20.加载核心控制器类
require_once BASEPATH.'core/Controller.php';
21.设置一个外部可调用框架app的类
function &get_instance()
{
return CI_Controller::get_instance();
}
22.加载自定义替换核心控制器类库
if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
{
require_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
}
23.基础类加载完成记录
$BM->mark('loading_time:_base_classes_end');
24.如果类不存在或者方法不存在则提示404
$e404 = FALSE;
$class = ucfirst($RTR->class);
$method = $RTR->method;
if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))
{
$e404 = TRUE;
}
else
{
require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');
if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
{
$e404 = TRUE;
}
elseif (method_exists($class, '_remap'))
{
$params = array($method, array_slice($URI->rsegments, 2));
$method = '_remap';
}
// WARNING: It appears that there are issues with is_callable() even in PHP 5.2!
// Furthermore, there are bug reports and feature/change requests related to it
// that make it unreliable to use in this context. Please, DO NOT change this
// work-around until a better alternative is available.
elseif ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class)), TRUE))
{
$e404 = TRUE;
}
}
if ($e404)
{
if ( ! empty($RTR->routes['404_override']))
{
if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2)
{
$error_method = 'index';
}
$error_class = ucfirst($error_class);
if ( ! class_exists($error_class, FALSE))
{
if (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'))
{
require_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php');
$e404 = ! class_exists($error_class, FALSE);
}
// Were we in a directory? If so, check for a global override
elseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php'))
{
require_once(APPPATH.'controllers/'.$error_class.'.php');
if (($e404 = ! class_exists($error_class, FALSE)) === FALSE)
{
$RTR->directory = '';
}
}
}
else
{
$e404 = FALSE;
}
}
// Did we reset the $e404 flag? If so, set the rsegments, starting from index 1
if ( ! $e404)
{
$class = $error_class;
$method = $error_method;
$URI->rsegments = array(
1 => $class,
2 => $method
);
}
else
{
show_404($RTR->directory.$class.'/'.$method);
}
}
if ($method !== '_remap')
{
$params = array_slice($URI->rsegments, 2);
}
25.执行per_controller 钩子
$EXT->call_hook('pre_controller');
26.设置控制器执行时间开始记录
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');
27.创建控制器对象
$CI = new $class();
28.执行控制器初始化钩子
$EXT->call_hook('post_controller_constructor');
29.调用回调函数,执行路由
call_user_func_array(array(&$CI, $method), $params);
30.设置控制器执行完成计时
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
31.执行控制器执行钩子
$EXT->call_hook('post_controller');
32.显示执行后的需要显示的内容
if ($EXT->call_hook('display_override') === FALSE)
{
$OUT->_display();
}
33.执行系统执行完成的钩子
$EXT->call_hook('post_system');
34.程序运行分析
大致运行的过程
1.index.php 文件作为前端控制器,初始化运行 CodeIgniter 所需的基本资源;
2.Router 检查 HTTP 请求,以确定如何处理该请求;
3.如果存在缓存文件,将直接输出到浏览器,不用走下面正常的系统流程;
4.在加载应用程序控制器之前,对 HTTP 请求以及任何用户提交的数据进行安全检查;
5.控制器加载模型、核心类库、辅助函数以及其他所有处理请求所需的资源;
6.最后一步,渲染视图并发送至浏览器,如果开启了缓存,视图被会先缓存起来用于 后续的请求。