首页 > php > CI源码分析

CI源码分析

作者:bin
目录
[隐藏]

楼主这里使用等ci版本为:2.2.0

一、index.php

定义开发环境:ENVIRONMENT

定义(define)文件路径:
SELF(当前文件名)、BASEPATH(system文件路径)、FCPATH(当前文件路径)、SYSDIR(框架文件路径)、APPPATH(应用目录)

引入核心文件:

require_once BASEPATH.’core/CodeIgniter.php’;

二、CodeIgniter.php

1、定义ci版本:

CI_VERSION

2、引入全局函数:

require(BASEPATH.’core/Common.php’);

Common中有几个相对重要的方法这里介绍以下:

load_class:类注册方法,这里遵循单例设计模式,会在APPPATH和BASEPATH以此查找文件,默认为libraries目录下,并且会压入is_loaded中

is_loaded :返回已加载的类

get_config:在APPPATH.’config/config.php’下查找配置文件,并且引入,判断$config是不是数组,之后遍历一遍,再返回$config

show_error:  打印错误并且exit

show_404:引入错误类,并且打印404错误;

log_message:引入日志类,并且打印日志;

3、引入常量:

根据环境引入常量config/constants.php,例如:

(defined)文件读写权限,图片目录,上传目录等;

4、判断php版本:

是否支持当前ci版本,如果小于5.2,关闭magic quotes

5、设置超时时间:

@set_time_limit(300);

6、加载benchmark类,计算运行时间:

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

开始全部计时

$BM->mark('total_execution_time_start');

开始基础类加载时间计时:

 $BM->mark('loading_time:_base_classes_start');

7、加载钩子类:

$EXT =& load_class('Hooks', 'core');

运行pre_system钩子:

$EXT->_call_hook('pre_system');

8、加载配置类:

$CFG =& load_class('Config', 'core');

引入配置文件(get_config上文有提到):

$this->config =& get_config();

如何没有设置base_url,那么就设置$this->config[base_url]为当前文件url

9、加载URI类:

$URI =& load_class('URI', 'core');

10、加载路由类:

 $RTR =& load_class('Router', 'core');

设置路由映射,根据URI请求确定应该提供什么服务:

$RTR->_set_routing();

_set_routing:

判断是否开启了enable_query_strings,开启了,就根据配置文件中的trigger,用$_GET去取controller、method等,并且设置,然后放入segments[]中。

然后引入用户配置文件中等Router.php,其中可以配置default_controller\404_override等页面

验证segments中等目录,文件,方法是否存在:

$this->_validate_request($segments);

设置默认控制器:

$this->_set_default_controller();

分解请求url:

$this->uri->_explode_segments();

将请求/home/index?id=1,分解成home/index?id=1,然后通过’/’炸成数组

explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string))

然后依次压入$segments中

$this->segments[] = $val;

解析url(⭐️)

$this->_parse_routes();

循环遍历

foreach ($this->routes as $key => $val)

循环自定义路由规则,看是否能命中当前uri地址

if (preg_match('#^'.$key.'$#', $uri))

设置请求:

$this->_set_request(explode('/', $val));

_set_request:

根据$segments中

如果count($segments) == 0 那么设置controller,否则设置class

如果!isset($segments[1])那么设置method=’index’,否则设置为method=$segments[1]

11、加载输出类

$OUT =& load_class('Output', 'core');

12、判断是否有可用等缓存文件,有就输出后结束脚本

if ($EXT->_call_hook('cache_override') === FALSE)

if ($OUT->_display_cache($CFG, $URI) == TRUE)

判断缓存是否输出:

$filepath = $cache_path.md5($uri);

文件是否存在:

if ( ! @file_exists($filepath))

是否超时:

if (time() >= trim(str_replace('TS--->', '', $match['1'])))

13、加载安全类,避免xss和csrf攻击

$SEC =& load_class('Security', 'core');

xss:大量正则,过滤html标签

csrf:种cookie验证唯一请求

14、加载输入类

$IN =& load_class('Input', 'core');

重现遍历输入($_GET、$_POST、$_COOKIE),

期间通过_clean_input_keys,过滤掉$config[permitted_uri_chars]中的字符

如果开启了csrf,那么进行验证

if ($this->_enable_csrf == TRUE && ! $this->is_cli_request())

$this->security->csrf_verify();

15、引入控制器基类

require BASEPATH.'core/Controller.php';

16、如果有自定义基类(继承上者),那么也引入

if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
 {
 require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
 }

17、判断请求uri中的控制器是否存在:

if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'))

18、引入uri中的控制器:

include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');

19、结束基础类加载计时:

$BM->mark('loading_time:_base_classes_end');

20、判断请求uri中的类和方法是否合法:

方法名不能以下划线开头

21、启动钩子pre_controller:

$EXT->_call_hook('pre_controller');

22、启动pre_controller计时器:

$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');

23、示例化请求的控制器:

$CI = new $class();

24、判断method是否存在:

if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))

25、执行方法:

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

26、结束controller的计时:

$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');

27、controller结束钩子方法执行:

$EXT->_call_hook('post_controller');

28、输出结果到browser

if ($EXT->_call_hook('display_override')

29、执行system结束钩子:

$EXT->_call_hook('post_system');

30、关闭数据库连接:

$CI->db->close();

您必须 [ 登录 ] 才能发表留言!