上一节我们研究了它的入口文件,那么接下来我们进入它的部引导类,就是codeigniter.php文件,这个文件略大,它的主要工作是统一全局的过程,因此,它的调用过程就是我们这个框架的执行流程.但是这个框架屏蔽了太多的细节问题,要探究具体的细节还得去具体的某一个类,因此,我们在研究这个类的时候,只需要知道它调用的哪些部分是为了完成哪些功能,而不必太过于着急去研究这个类的功能.我们后面会再次分析它的具体实现方式的.
它的功能如下:
1.设置配置项,配置是非常重要的,而配置往往又及其的复杂,有可能来自于写入文件的配置项,有可能来自于数据库中,还有可能被动态的修改,因此,考虑到配置项来源的复杂性,那么你是怎么处理的呢?ci框架通过一个配置类来处理它.
2.加载各个功能类,在加载完相应类之后有可能需要调用相应的函数来进行简单操作,毕竟一个类的构造函数不可能完成所有的工作.
3.我们需要仔细权衡的就是它加载各个类的顺序和各个类的功能,比如说在分析url的这一功能上,判断url的模式,防注入,动态生成url,url出现问题的解决方式等等.其实呢,随着我们解析的深入,这些问题都会给出一个解决方案,不一定最好,但是绝对可行.
废话不多说,直接上源码,另外就是我写的注释,感觉只要大家懂得php的语法和汉字,看懂是没问题的,如果有错误之处,也请指出.
4.该流程的主要是判断该类的该方法是否存在,然后调用相应的方法即可了 .当然路由类势必要起到很大的作用.
-
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-
//定义CI的版本.
-
define('CI_VERSION', '2.0');
-
//加载全局函数.
-
require(BASEPATH.'core/Common'.EXT);
-
//加载应用程序的常量.
-
require(APPPATH.'config/constants'.EXT);
-
//定义错误处理函数
-
set_error_handler('_exception_handler');
-
//判断PHP版本.
-
if ( ! is_php('5.3'))
-
{
-
@set_magic_quotes_runtime(0);
-
}
-
-
//设置子类的前缀,这在多个应用同时出现时比较有用,比如可以设置"A_"和"B_"来区分.
-
if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '')
-
{
-
get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
-
}
-
-
//设置一个自由的脚本执行时间限制.
-
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');
-
//实例化钩子类.什么是钩子和钩子的作用及其实现在钩子类里仔细分析.
-
$EXT =& load_class('Hooks', 'core');
-
//是否有系统开始前的钩子.
-
$EXT->_call_hook('pre_system');
-
//实例化配置类.
-
$CFG =& load_class('Config', 'core');
-
//我们是否需要手工去修改配置项
-
if (isset($assign_to_config))
-
{
-
$CFG->_assign_to_config($assign_to_config);
-
}
-
//实例化UTF8类.
-
$UNI =& load_class('Utf8', 'core');
-
//实例化URI类.
-
$URI =& load_class('URI', 'core');
-
//实例化路由类,并且设置路由.
-
$RTR =& load_class('Router', 'core');
-
$RTR->_set_routing();
-
//在index.php里可以覆盖默认的路由.
-
if (isset($routing))
-
{
-
$RTR->_set_overrides($routing);
-
}
-
//实例化输出类,具体功能到output类里分析.
-
$OUT =& load_class('Output', 'core');
-
//是否有相应的缓存,如果有缓存文件,则直接使用相应的缓存文件.
-
if ($EXT->_call_hook('cache_override') === FALSE)
-
{
-
if ($OUT->_display_cache($CFG, $URI) == TRUE)
-
{
-
exit;
-
}
-
}
-
//加载input类.
-
$IN =& load_class('Input', 'core');
-
//加载语言类.
-
$LANG =& load_class('Lang', 'core');
-
-
//引入基控制器
-
require BASEPATH.'core/Controller'.EXT;
-
//得到控制器的实例,这个方法会经常用到.
-
function &get_instance()
-
{
-
return CI_Controller::get_instance();
-
}
-
-
//如果存在子类应用的基控制器,则加载它.
-
if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller'.EXT))
-
{
-
require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller'.EXT;
-
}
-
-
-
//使用路由类来加载具体的控制器,如果文件不存在,则报错.
-
if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().EXT))
-
{
-
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().EXT);
-
-
//为测试开始计时.
-
$BM->mark('loading_time:_base_classes_end');
-
-
-
//安全检测,通过路由取得的类和方法进行判断.
-
$class = $RTR->fetch_class();
-
$method = $RTR->fetch_method();
-
//如果类或方法有问题,则定义404 not found.
-
//这里的404涉及到http协议,请参考其他内容.
-
if ( ! class_exists($class)
-
OR strncmp($method, '_', 1) == 0
-
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
-
)
-
{
-
show_404("{$class}/{$method}");
-
}
-
-
//在控制器之前是否要执行钩子?
-
$EXT->_call_hook('pre_controller');
-
-
//实例化请求的控制器类并且开始计时.
-
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');
-
-
$CI = new $class();
-
-
//在控制器的构造时是否需要执行钩子.
-
$EXT->_call_hook('post_controller_constructor');
-
-
//调用钩子定义的函数,
-
//分析方法是否被重写,即开启了重写模式.如果是我们调用后者.
-
if (method_exists($CI, '_remap'))
-
{
-
$CI->_remap($method, array_slice($URI->rsegments, 2));
-
}
-
else
-
{
-
-
//is_callable()在php 5的某些版本里面,对于private和protected方法会返回true.
-
if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
-
{
-
//如果该方法根本就不存在,进行相应的处理.
-
if ( ! empty($RTR->routes['404_override']))
-
{
-
$x = explode('/', $RTR->routes['404_override']);
-
//$x的第一个参数为相应的类.
-
$class = $x[0];
-
//$x的第二个参数为相应的方法,如果没有默认为index
-
$method = (isset($x[1]) ? $x[1] : 'index');
-
if ( ! class_exists($class))
-
{
-
if ( ! file_exists(APPPATH.'controllers/'.$class.EXT))
-
{
-
show_404("{$class}/{$method}");
-
}
-
-
include_once(APPPATH.'controllers/'.$class.EXT);
-
unset($CI);
-
$CI = new $class();
-
}
-
}
-
else
-
{
-
show_404("{$class}/{$method}");
-
}
-
}
-
-
-
-
//任何一个uri段会被会被便利的通过该方法调用.
-
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
-
}
-
-
-
//在方法执行完之后记录时间.
-
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
-
-
//调用post_controller的钩子.
-
$EXT->_call_hook('post_controller');
-
-
//是否有展示的时候被重写的钩子.
-
if ($EXT->_call_hook('display_override') === FALSE)
-
{
-
$OUT->_display();
-
}
-
-
//在post_system里是否有钩子.
-
$EXT->_call_hook('post_system');
-
-
//如果数据库未关闭,则关闭数据库.
-
if (class_exists('CI_DB') AND isset($CI->db))
-
{
-
$CI->db->close();
-
}
阅读(1018) | 评论(0) | 转发(0) |