前言
CI框架Router路由类将URI映射到对应的控制器及方法,Router类大量代码处理的是自定义路由,该类要支撑以下几个功能点:
- 自定义路由规则:在application/config/routes.php文件中的$route数组,利用它可以设置路由规则,在路由规则中可以使用通配符或正则表达式,比如:
$route['product/:num'] = 'catalog/product_lookup'; $route['products/([a-z]+)/(\d+)'] = $1/id_$2;
; - 支持回调函数:在路由规则中使用回调函数来处理逆向引用,比如:
$route['products/([a-zA-Z]+)/edit/(\d+)'] = function ($product_type, $id){return 'catalog/product_edit/' . strtolower($product_type) . '/' . $id;};
; - 支持使用HTTP动词:在路由数组后面再加一个键,键名为HTTP动词,可以使用标准的 HTTP 动词(GET、PUT、POST、DELETE、PATCH),也可以使用自定义的动词 (例如:PURGE),不区分大小写。比如:
$route['products']['put'] = 'product/insert';
;
⏸️这里不妨也先暂停思考下,如果要求支持以上的自定义路由规则,你写时要打算如何处理呢?。。。。。。
好,我们先看下CI框架中路由类的实现框架:
1 | //CI_Config class object |
构造函数__contruct()
Router::class构造函数实例化的过程,就已经完成了路由的解析过程,得到请求的控制器和方法名。
1 | public function __contruct($routing = NULL){ |
核心解析函数_set_routing()
加载config file中自定义的路由规则,将uri string($this->enable_query_strings=TRUE时路由直接从querystring中解析)通过_parse_routes()
解析映射到合理的directory,class和method。
1 | protected function _set_routing(){ |
解析自定义路由规则_parse_routes()
根据config/routes.php中自定义的路由规则【通配符和正则表达式,回调函数,HTTP动词】,逐个匹配$this->uri,若有命中则将此路由片段中传递给_set_request
处理,否则直接将$this->uri->segments传递给_set_request
。
1 | protected function _parse_routes(){ |
_set_request($segments)
首先调用$this->_validate_request
解析segments目录,然后根据segments映射出控制器,方法名,并更新设置$this->uri->rsegments。
1 | protected function _set_request($segments = array()){ |
_validate_request($segments)
检测寻找出一个正确存在的路由,主要是在于处理多级目录,重置$this->directory。
1 | protected function _validate_request($segments){ |
_set_default_controller()
由$this->default_controller,设置对应的控制器,方法和$this->uri->rsegments。
1 | protected function _set_default_controller(){ |
Route::class的属性函数簇
set_class($class),fetch_class();
set_method($method),fetch_method()
set_directory($dir, $append = FALSE)
1 | public function set_class($class) |
总结
CI_Router路由类将uri string根据定义的路由规则(包括自定义路由规则)映射到对应的控制器及方法,待以后续调用处理请求。最后,我们再次来梳理下路由解析类的CI执行流程: