CI路由剖析

来源:互联网 发布:linux的7种运行级别 编辑:程序博客网 时间:2024/05/22 15:42

CI 的路由功能是在CodeIninter.PHP文件中开始执行的。
1:在核心文件CodeIninter.php中,加载完路由操作类Router之后,立刻就执行了$RTR->_set_routing();该方法主要的功能是:
a:在初始化路由类的时候加载了配置类Config,和URI操作类两个文件
b:首先判断是否开启了:enable_query_strings,如果是,那么执行以下:
(1):通过用$_GET['c']和$_GET['m']来获取当前的类和方法,并放到数组$segments中。
c:加载APPPATH/config/routes.php(路由配置文件),放到$this->routes中,然后释放routes.php中的$routes
d:获取默认的Controller($this->default_controller),转换成首字母大写
e:判断$segments数组是否为空(该变量的数据来源于可能的b步骤),如果执行了b步骤,显然不会为空,会调用方法$this->_validate_request($segments)来处理
f:方法_validate_request()的主要功能是:判断$segments中指定的控制器文件是否存在,存在,返回,不存在,判断是否存在子层目录,如果存在,进行相关处理。
g:调用URI中_fetch_uri_string方法:通过各种方法获取URI的内容(首先考虑的是 REQUEST_URI),将处理后的URI放到$this->uri_string中
h:判断$this->uri_string是否为空,若是:调用_set_default_controller();
1:设置默认的控制器,我们在路由配置文件中可以这么写:$route['default_controller'] = “Home/test”;,那么解析后,控制器为home,方法为test
2:然后调用方法_set_request():功能是先调用_validate_request(),判断控制器和方法是否存在,然后就是设置Router中class和method属性的值。
i:判断是否存在URL的后缀,如果有那么就调用URI中的_remove_url_suffix()方法来处理,
j:调用URI中的方法:_explode_segments()来将处理后的URI字符串转换成数组的形式存放到$this->segments[]数组中。
k:调用Router中的方法_parse_routes来解析用户自定义的路由。
1:该方法主要是判断用户是否自定义了路由,然后根据当前的URI信息来匹配用户自定义的路由,如果匹配上了的话,就调用_set_request()来设置当前操作类和方法,以实现路由的功能。代码:

view sourceprint?
01.//将URI参数数组用/重新组合
02.$uri = implode('/', $this->uri->segments);
03. 
04.// 判断当前的uri是否已被路由定义,
05.if (isset($this->routes[$uri]))
06.{
07.//直接设置路由中的类和方法还有参数
08.return $this->_set_request(explode('/', $this->routes[$uri]));
09.}
10. 
11.// 遍历自定义的路由信息,以寻找和当前uri相匹配的数据
12.foreach ($this->routes as $key => $val)
13.{
14.// 替换CI自定义的规则为正则
15.$key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
16. 
17.// 执行当期uri和路由匹配
18.if (preg_match('#^'.$key.'$#', $uri))
19.{
20.// $route['category/(:any)'] = 'home/category/$1';
21.if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
22.{
23.$val = preg_replace('#^'.$key.'$#', $val, $uri);
24.}
25.//直接设置路由中的类和方法还有参数
26.return $this->_set_request(explode('/', $val));
27.}
28.}
29.//设置默认的路由信息
30.$this->_set_request($this->uri->segments);

l:最后调用函数$this->uri->_reindex_segments();来重置索引,确保数组$segments是从1开始的。
//=======================================================================================================
上面的操作都是在CI核心文件CodeIninter.php调用$RTR->_set_routing()方法所执行的操作
简单的概括就是:
通过URI类和Router类的操作来获取当前控制器和操作方法,如果不存在,那么就调用默认的控制器方法,然后结合用户自定义的路由信息。将当前要操作的控制器和方法存起来,然后我们通过方法$class = $RTR->fetch_class();$method = $RTR->fetch_method();就可以获取要操作的对象了另外,还将URI中其他的参数放到URI类的变量$this->segments[]中,我们只要从这个变量当中取就OK了
所以CI只要这样子call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));就可以驱动我们自己写代码和获取参数了。
那么整个项目也就跑起来了。
//================================================================================
PS:
CI提供了一个临时路由的方法:我们在CodeIninter.PHP文件中看到这么一行:

view sourceprint?
1.if (isset($routing))
2.{
3.$RTR->_set_overrides($routing);
4.}

如果我们index.php文件中有设置这样子一个数组:

view sourceprint?
1.$routing['directory'] = '';//设置子控制器目录,一般为空
2.$routing['controller'] = 'Home';//控制器
3.$routing['function'] = ''; //方法

那么之前所有的路由解析将是作废的,系统会按照这个$routing数组定义的控制器和方法来运行你的程序。


原创粉丝点击