CodeIgniter 框架最显著的特征就是 MVC 模式,它的做法就是提取 url 中的“分段”, 映射到某个类的某个方法,从而由该方法来输出最终显示的页面内容。
尽管 CodeIgniter 已经很精简,但是对于讲解来说,代码还是稍显多了一些。所以这里只是按照 CodeIgniter 的思路,重新走一次框架的流程。注意,可能会与 CodeIgniter 代码有差异,但是思路是一致的。
我们先来看看入口文件 index.php,先大略了解下。然后再慢慢深入到具体的类与方法的设计。index.php 设计如下,注释已经解释得比较明显了:
/**
* 框架主入口文件,所有的页面请求均定为到该页面,并根据 url 地址来确定调用合适的方法并显示输出
*/
define('APPPATH', '');
// 自动加载所需的类
require('core/Common.php');
// 加载 core/URI.php 类
$URI =& load_class('URI');
// 加载 core/Router.php 类
$RTR =& load_class('Router');
// 调用 Router.php 类的 set_routing() 方法,抽取路由信息
$RTR->set_routing();
// 抽取路由中的 class 名与 method 名
$class = $RTR->fetch_class();
$method = $RTR->fetch_method();
// 加载 core/Controller.php 类
require('core/Controller.php');
function &get_instance() {
return CI_Controller::get_instance();
}
// 根据 class 名加载控制器
require('controllers/'.$class.'.php');
// new 一个控制器的对象,$class 就是控制器的名
$CI = new $class();
/*
echo '
';
print_r( $URI->rsegments );
print_r(array(&$CI, $method));
print_r(array_slice($URI->rsegments, 2));
echo '
';*/
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 1));
//call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
index.php 的大致流程是:
require('core/Common.php'); 加载 core/Common.php,这个类具有 function &load_class() 方法,以方便加载其它的类;
$URI =& load_class('URI'); 加载 core/URI.php,这个类的作用是分析 URI, 并决定路由,后面后详细介绍;
$RTR =& load_class('Router'); 加载 core/Router.php,这个类可以抽取路由的class 名与 method 名。
然后 require('core/Controller.php'); 加载 core/Controller.php,准备加载具体的控制器;
$CI = new $class(); 根据加载的控制器,new一个对象;
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 1)); 根据对象创建方法。
流程似乎也很简单。
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 1)); 似乎有点不容易理解:
call_user_func_array函数也可以调用类内部的方法的:
Class ClassA
{
function bc($b, $c) {
$bc = $b + $c;
echo $bc;
}
}
call_user_func_array(array('ClassA','bc'), array("111", "222"));
//显示 333
我们可以 print_r( $URI->rsegments ); 看看结果:
Array
(
[0] => welcome
[1] => nowamagic
)
再 print_r(array(&$CI, $method)); 看看里面是怎样的:
Array
(
[0] => welcome Object
(
[uri] => CI_URI Object
(
[segments] => Array
(
[0] => welcome
[1] => nowamagic
)
[uri_string] => welcome/nowamagic
[rsegments] => Array
(
[0] => welcome
[1] => nowamagic
)
)
[router] => CI_Router Object
(
[uri] => CI_URI Object
(
[segments] => Array
(
[0] => welcome
[1] => nowamagic
)
[uri_string] => welcome/nowamagic
[rsegments] => Array
(
[0] => welcome
[1] => nowamagic
)
)
[routes] => Array
(
[default_controller] => home
[welcome/nowamagic] => welcome/nowamagic
)
[class] => welcome
[method] => nowamagic
[default_controller] => home
)
[load] => CI_Loader Object
(
[_ci_model_paths:protected] => Array
(
[0] =>
)
[_ci_models:protected] => Array
(
)
)
)
[1] => nowamagic
)
看起来东西有点多,但实质上还是保存着一些 uri 和 router 信息而已。从 index.php 我们可以感受到,CI 是如何将 url 映射到具体的方法。