好久没有更新Blog了,前一段时间在研究nginx源码。相比redis,nginx的代码量要多几倍,结构也比较复杂,稍后将补充nginx的源码分析。
在研究nginx的同时,笔者也开始着手阅读CodeIgniter源码。CodeIgniter是一款非常流行且轻量级的框架。CodeIgniter,设计灵活,扩展性强,低耦合。
在阅读源码CodeIgniter3.0.0的时候,笔者发现Router.php的一个BUG,此BUG在后期的版本已修复。
protected function _set_routing()
{
if ($this->enable_query_strings)
{
$_d = $this->config->item('directory_trigger');
$_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
if ($_d !== '')
{
$this->uri->filter_uri($_d);
$this->set_directory($_d);
}
//获取control参数
$_c = trim($this->config->item('controller_trigger'));
if ( ! empty($_GET[$_c]))
{
$this->uri->filter_uri($_GET[$_c]);
$this->set_class($_GET[$_c]);
//获取方法
$_f = trim($this->config->item('function_trigger'));
if ( ! empty($_GET[$_f]))
{
$this->uri->filter_uri($_GET[$_f]);
$this->set_method($_GET[$_f]);
}
$this->uri->rsegments = array(
1 => $this->class,
2 => $this->method
);
}
else
{
$this->_set_default_controller();
}
// Routing rules don't apply to query strings and we don't need to detect
// directories, so we're done here
return;
}
//加载routes配置文件
if (file_exists(APPPATH.'config/routes.php'))
{
include(APPPATH.'config/routes.php');
}
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
// Validate & get reserved routes
if (isset($route) && is_array($route))
{
isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
unset($route['default_controller'], $route['translate_uri_dashes']);
$this->routes = $route;
}
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
$this->_parse_routes();
}
else
{
$this->_set_default_controller();
}
}
从上面的代码可以看出,当$this->enable_query_strings
条件为true
时,系统首先会判断url是否带有controller_trigger
配置参数。若存在,则继续获取function_trigger
配置参数值;若不存在,则调用$this->_set_default_controller()
方法。而此时,$this->_set_default_controller
并未定义。so,此时访问会出现报错的情况。简而言之,就是在$this->enable_query_strings
为True时,/index.php访问会出现报错。
解决方法:只要把line42~60行的代码放置该流程之前运行。
protected function _set_routing()
{
// Load the routes.php file.
//修复CI框架BUG,default_controller放在函数顶部进行初始化
//加载routes配置文件
if (file_exists(APPPATH.'config/routes.php'))
{
include(APPPATH.'config/routes.php');
}
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
// Validate & get reserved routes
if (isset($route) && is_array($route))
{
isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
unset($route['default_controller'], $route['translate_uri_dashes']);
$this->routes = $route;
}
if ($this->enable_query_strings)
{
$_d = $this->config->item('directory_trigger');
$_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
if ($_d !== '')
{
$this->uri->filter_uri($_d);
$this->set_directory($_d);
}
//获取control参数
$_c = trim($this->config->item('controller_trigger'));
if ( ! empty($_GET[$_c]))
{
$this->uri->filter_uri($_GET[$_c]);
$this->set_class($_GET[$_c]);
//获取方法
$_f = trim($this->config->item('function_trigger'));
if ( ! empty($_GET[$_f]))
{
$this->uri->filter_uri($_GET[$_f]);
$this->set_method($_GET[$_f]);
}
$this->uri->rsegments = array(
1 => $this->class,
2 => $this->method
);
}
else
{
$this->_set_default_controller();
}
// Routing rules don't apply to query strings and we don't need to detect
// directories, so we're done here
return;
}
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
$this->_parse_routes();
}
else
{
$this->_set_default_controller();
}
}
总结
很多开源软件之所以优秀,并不在于它的代码有多么美观,而是在于它的设计思想。很多时候我们只掌握了它的用法,并未理解它真正的含义。如果能耐心地测试,加以推敲,我们就能快速地理解它的意图,了解其设计的精髓。