? ? ? ? ?上篇文章當(dāng)中我們提到实牡,在CodeIgniter.php中,解析出你訪問的url所對應(yīng)的controllers和action,然后在調(diào)用call_user_func_array()方法,進(jìn)入到action中岳守,而這里是如何得到這個對應(yīng)關(guān)系的呢,這就是我們現(xiàn)在要討論的內(nèi)容碌冶。
1湿痢、CodeIgniter.php
?我們首先來到CodeIgniter.php,發(fā)現(xiàn)這其實是在Router類中實現(xiàn)的扑庞,如下源碼:
$RTR =& load_class('Router', 'core', isset($routing) ? $routing : NULL);
$class = ucfirst($RTR->class);
$method = $RTR->method;
2譬重、Router.php
我們進(jìn)去Router.php中一探究竟,Router類中的構(gòu)造函數(shù)核心是這里:
$this->_set_routing();
_set_routing方法其實核心做這幾步操作:
$_d = $this->config->item('directory_trigger');
$this->set_directory($_d);
$_c = trim($this->config->item('controller_trigger'));
$this->set_class($_GET[$_c]);
$_f = trim($this->config->item('function_trigger'));
$this->set_method($_GET[$_f]);
$this->_parse_routes();
分別從全局變量_GET數(shù)組中獲取 directory,class,method,他們的trigger可以在配置文件中配置罐氨。當(dāng)然這是在 enable_query_strings 設(shè)置為true的情況下臀规。接下來就進(jìn)入了最關(guān)鍵的方法中_parse_routes方法:
我們在CI的路由配置中,可以如下配置:
$route['products']['put']='product/insert';
就是因為在_parse_routes中的這段代碼:
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
$val = array_change_key_case($val, CASE_LOWER);
if (isset($val[$http_verb])){
$val = $val[$http_verb];}
else{continue;}
HTTP verbs (GET, PUT, POST, DELETE, PATCH) 有這么幾種.而我們在配置中可以這么配置:
$route['product/(:num)']='catalog/product_lookup_by_id/$1';
是因為_parse_routes中的這段代碼:
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
路由配置中更加可以配置回調(diào)函數(shù)如:
$route['products/([a-zA-Z]+)/edit/(\d+)']=function($product_type,$id){return'catalog/product_edit/'.strtolower($product_type).'/'.$id;};
是因為有這段代碼:
if ( ! is_string($val) && is_callable($val)){
array_shift($matches);
$val = call_user_func_array($val, $matches);
}
而一般的配置:
else if (strpos($val, ') !== FALSE && strpos($key, '(') !== FALSE){
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
最后調(diào)用了:
$this->_set_request(array_values($this->uri->segments));
_set_request方法當(dāng)中
$this->set_class($segments[0]);
if (isset($segments[1])){
$this->set_method($segments[1]);
}else{
$segments[1] = 'index';
}
set了class和method,這就得到了我們在開始CodeIgniter.php中所需要的class和method
3栅隐、Uri.php
這里要說下這個上面uri的來路:
$uri = implode('/', $this->uri->segments);
我們進(jìn)入Uri類中查看究竟:
核心的方法是_parse_request_uri塔嬉,在方法體中,
$uri = parse_url('http://dummy'.$_SERVER['REQUEST_URI']);
$query = isset($uri['query']) ? $uri['query'] : '';
$uri = isset($uri['path']) ? $uri['path'] : '';
return $this->_remove_relative_directory($uri);
主要是用parse_url解析出url當(dāng)中的path和query租悄,然后進(jìn)行去除相對路徑的處理谨究。
$this->uri->segments這個成員變量中存儲的就是explode('/', trim($uri, '/') 后的數(shù)組,在_set_uri_string方法中賦值泣棋。