CodeIgniter源码分析之Routerphp.docx

上传人:b****5 文档编号:6238196 上传时间:2023-01-04 格式:DOCX 页数:19 大小:20.83KB
下载 相关 举报
CodeIgniter源码分析之Routerphp.docx_第1页
第1页 / 共19页
CodeIgniter源码分析之Routerphp.docx_第2页
第2页 / 共19页
CodeIgniter源码分析之Routerphp.docx_第3页
第3页 / 共19页
CodeIgniter源码分析之Routerphp.docx_第4页
第4页 / 共19页
CodeIgniter源码分析之Routerphp.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

CodeIgniter源码分析之Routerphp.docx

《CodeIgniter源码分析之Routerphp.docx》由会员分享,可在线阅读,更多相关《CodeIgniter源码分析之Routerphp.docx(19页珍藏版)》请在冰豆网上搜索。

CodeIgniter源码分析之Routerphp.docx

CodeIgniter源码分析之Routerphp

phpif(!

defined('BASEPATH'))exit('Nodirectscriptaccessallowed');

//------------------------------------------------------------------------

/**

*RouterClass

*/

classCI_Router{

/**

*Configclass

*/

var$config;

/**

*Listofroutes

*/

var$routes=array();

/**

*Listoferrorroutes

*/

var$error_routes=array();

/**

*Currentclassname

*/

var$class='';

/**

*Currentmethodname

*/

var$method='index';

/**

*Sub-directorythatcontainstherequestedcontrollerclass

*/

var$directory='';

/**

*Defaultcontroller(andmethodifspecific)

*/

var$default_controller;

/**

*Constructor

*/

function__construct()

{

$this->config=&load_class('Config','core');

$this->uri=&load_class('URI','core');

log_message('debug',"RouterClassInitialized");

}

//--------------------------------------------------------------------

/**

*Settheroutemapping

*/

function_set_routing()

{

//如果项目是允许通过query_strings的形式,并且有通过$_GET的方式请求控制器的话,则以query_string形式,也就是

//?

c=xx的形式确定路由。

$segments=array();

if($this->config->item('enable_query_strings')===TRUEANDisset($_GET[$this->config->item('controller_trigger')]))

{

//上面这里为什么还要判断有没有通过get的方式指定控制器?

其实是因为如果允许query_string的形式请求路由,但是却

//没有通过query_string(或者说是get)的形式指定路由的话(其实就说明这个通过query_string方式的uri是无效的),

//此时,我们依然会采用“段”的形式。

//取得目录名,目录名,控制名和方法名传递的变量名都是可以自定义的,在config/config.php里面。

if(isset($_GET[$this->config->item('directory_trigger')]))

{

$this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')])));

$segments[]=$this->fetch_directory();

}

//取得控制器名

if(isset($_GET[$this->config->item('controller_trigger')]))

{

$this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));

$segments[]=$this->fetch_class();

}

//取得方法名

if(isset($_GET[$this->config->item('function_trigger')]))

{

$this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));

$segments[]=$this->fetch_method();

}

}

//。

位置1

//Loadtheroutes.phpfile.

//引入关于路由方面的配置信息。

配置文件里面是一个名字为$route的数组。

if(defined('ENVIRONMENT')ANDis_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))

{

include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');

}

elseif(is_file(APPPATH.'config/routes.php'))

{

include(APPPATH.'config/routes.php');

}

//下面这个莫名出现的$route变量(注意不是$this->routes哦),就是写在配置文件里面。

把它copy到$this->routes。

//这个$routes是用来指定默认控制器和默认方法,404(请求路由不存在)后规定的路由以及一些路由重定向(?

这个重写向的

//实现在Router:

:

_parse_routes()中实现)的信息。

$this->routes=(!

isset($route)OR!

is_array($route))?

array():

$route;

unset($route);//利用完就干掉。

//根据刚才的配置信息,设定默认控制器,没有的话,就为FLASE。

$this->default_controller=(!

isset($this->routes['default_controller'])OR$this->routes['default_controller']=='')?

FALSE:

strtolower($this->routes['default_controller']);

//这个判断的位置放得有点怪,我觉得可以放到上面“位置1”的地方,下面的代码是判断刚才有没有通过query_string的方式拿到

//路由信息,如果拿到的话,那么就不再尝试“段”的方式确定路由了。

直接确定路由,结束本函数。

if(count($segments)>0)

{

//_validate_quest($segments);的作用就是确定并设置路由。

//这个函数执行完之后,Router:

:

$class,Router:

:

$directory(如果有)都会有相应值。

return$this->_validate_request($segments);

}

//下面的_fetch_uri_string()详见:

URI.php,在这个位置只需知道它的作用是:

//从uri中检测处理,把我们确定路由需要的信息(例如“index.php/index/welcome/1”后

//面"index/welcome/1"这串)放到$this->uri->uri_string这个东西中。

$this->uri->_fetch_uri_string();

//上面_fetch_uri_string()完了之后,这个uri_string就会有我们要用的信息,如果为空的话,那么就用把路由设置为默认的。

if($this->uri->uri_string=='')

{

//移步至Router:

:

_set_default_controller();

return$this->_set_default_controller();

}

//如果$this->uri->uri_string不为空,那么,会通过下面的方式确定路由

//这里只是简单地把后缀去掉而已,因为CI允许在uri后面加后缀,但它其实对我们寻找路由是多余,而且会造成影响的,所以先去掉。

$this->uri->_remove_url_suffix();

//把最初的uri,变成数组放在segments里面。

$this->uri->_explode_segments();

//开始找路由。

移步至Router:

:

_parse_routes();

$this->_parse_routes();

//设置为由1开始。

$this->uri->_reindex_segments();

}

//--------------------------------------------------------------------

/**

*Setthedefaultcontroller

*/

function_set_default_controller()

{

//在Router:

:

_set_routing()函数里面有一个操作,是从配置文件里面读取默认控制器名,如果没有就有FALSE。

if($this->default_controller===FALSE)

{

//如果没有默认的话,就报错,结束程序。

//实质上,这个_set_default_controller()仅仅是在uri没有指定控制器,要求访问默认控制器的时候才

//被调用,所以如果连默认控制器都没有,那么可以果断报错。

show_error("Unabletodeterminewhatshouldbedisplayed.Adefaultroutehasnotbeenspecifiedintheroutingfile.");

}

//如果有,下面我们就来把默认的控制器设置为当前要找的路由。

//这里只是分“有指定默认方法”和“没有指定”两种情况而已。

不过要弄点下面那个$this->_set_request($x);CI这几个函数

//也许写得很妙,但是让人看得纠结。

if(strpos($this->default_controller,'/')!

==FALSE)

{

$x=explode('/',$this->default_controller);

$this->set_class($x[0]);

$this->set_method($x[1]);

$this->_set_request($x);//移步至Router:

:

_set_request();

}

else

{

$this->set_class($this->default_controller);

$this->set_method('index');

$this->_set_request(array($this->default_controller,'index'));

}

//re-indextheroutedsegmentsarraysoitstartswith1ratherthan0

$this->uri->_reindex_segments();

log_message('debug',"NoURIpresent.Defaultcontrollerset.");

}

//--------------------------------------------------------------------

/**

*SettheRoute

*/

function_set_request($segments=array())

{

/**

*下面来解剖一下这个让人纠结的函数。

第一次看的时候差点被它们这几个函数搞晕。

*/

/**

*看,这里有调用Router:

:

_validate_request();而Router:

:

_validate_request()的作用是检测寻找出一个

*正确存在的路由,并确定它,确定后的值分别放到Rouer:

:

$class这些属性里面。

所以使到这个_set_request()也有

*这种确定路由的功能。

*

*注:

*$segments=$this->_validate_request($segments);等式右边,括号里面的这个$segments,也就是调用

*_set_request()时传入来的这个参数,它有这样的特点:

*1)如果这时_set_request()是在Router:

:

_set_default_controller()中调用的话,那个这个$segments是永远不会为

*空数组,嗯,绝对不会。

*

*

*而左边这个$segments的值,经过下面这行代码后,要么为空数组array(),要么为确定路由后的段数组。

*为空数组的原因是,$this->_validate_request();里面没有找到当前目录的默认控制器。

此时,右边的

*$segments要么为空,要么只指定了目录但默认控制器不存在。

*/

$segments=$this->_validate_request($segments);

if(count($segments)==0)

{

//所以如果上面返回了空数组,就会进到这里。

//这里居然又调回了_set_default_controller()!

坑爹吧!

return$this->_set_default_controller();

/**

*我曾经想过,下面这里会不会死循环:

*假如,我在配置文件里面的默认控制器设为welcome,然后controllers/下没有welcome.php,但controllers/下有

*welcome/有这个目录(里面没东西),然后通过http:

//localhost/CI/来访问默认控制器,那会怎样呢?

*首先,它会进入_set_routing();然后发现$this->uri->uri_string为空,进入_set_default_controller();

*然后发现在_set_default_controller里,发现$this->default_controller不为FALSE,(@@@@),然后再

*进入这_set_request()里面,再进入_validate_request()里面,会不会_validate_request里返回空数组?

因为

*指定了目录,没有指定控制器,访问默认的,又不存在,然后返回空数组,返回空数组后,最终就会走来你正在看的这个位置,

*然后这个位置再调用_set_default_controller();然后死循环了。

*

*答案是不会的。

*原因在于:

*我们回到上面解译那个(@@@@)的地方,在这里,发现$this->default_controller不为FALSE后,它会进入这个else

*里面

*else

*{

*$this->set_class($this->default_controller);..............1

*$this->set_method('index');...................2

*$this->_set_request(array($this->default_controller,'index'));..........3

*}

*

*然后第3行,传入_set_request($segments)中的那个$segments其实是

*array('welcome','index'),重点在于那个小小的'index'!

!

!

!

!

!

!

*这样一来,我们进入_validate_request()的时候,我们实质并没有“指定目录但没有指定控制器,访问默认控制器”,

*而是“指定了一个welcome的目录,和一个叫index的控制器!

”,所以才不会死循环。

*如果你试着把第3行那个'index'去掉,那么,一定会死循环!

不信试试!

CI太牛逼了,居然这样做。

汗。

*当然,‘index’还有一个作用,就是设置默认方法啦。

*/

}

$this->set_class($segments[0]);

if(isset($segments[1]))

{

//Astandardmethodrequest

$this->set_method($segments[1]);

}

else

{

$segments[1]='index';

}

//这里要说一下,现在是在ROUTER里面为URI赋值,URI里面的这个URI:

:

$rsegments是经过处理,并确定路由后,实质调用的路由的段信息。

//而URI:

:

$segments(前面少了个r),则是原来没处理前的那个,即直接由网址上面得出来的那个。

$this->uri->rsegments=$segments;

}

//--------------------------------------------------------------------

/**

*Validatesthesuppliedsegments.Attemptstodeterminethepathto

*thecontroller.

*/

function_validate_request($segments)

{

if(count($segments)==0)

{

return$segments;

}

if(file_exists(APPPATH.'controllers/'.$segments[0].'.php'))

{

//如果直接在controllers这个目录下找到与第一段相应的控制器名,那就说明找到了控制器,确定路由,返回。

return$segments;

}

//如果上面没有找到,再看看这个“第一段”是不是一个目录,因为CI是允许控制器放在自定义的目录下的。

if(is_dir(APPPATH.'controllers/'.$segments[0]))

{

//Setthedirectoryandremoveitfromthesegmentarray

//如果的确是目录,那么就可以确定路由的目录部分了。

$this->set_directory($segments[0]);

//去掉目录部分。

进一步进行路由寻找。

$segments=array_slice($segments,1);

//如果uri请求中除了目录还有其它“段”,那说明是有请求某指定控制器的。

if(count($segments)>0)

{

//指定请求的控制器找不到的话,那只好报错了。

if(!

file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))

{

//报错也有两方式,一种是默认的,一种是自义定的。

//下面这个404_override就是在config/routes.php定义的一个路由找不到时候的默认处理控制器了,如果有定义

//我们调用它。

if(!

empty($this->routes['404_override']))

{

$x=explode('/',$this->routes['404_override']);

$this->set_directory('');//把刚才设置好的路由的目录部分去掉,因为现在路由是我们定义的404路由。

$this->set_class($x[0]);//这里可以看出,我们定义的404路由是不允许放在某个目录下的,只能直接放在controllers/下

$this->set_method(isset($x[1])?

$x[1]:

'index');//默认是index方法

return$x;//同样,返回“段”数组

}

else

{

//默认找不到路由的方法。

在core/Common.php中定义的全局函数(实质调用Exception组件进行处理)。

show_404($this->fetch_directory().$segments[0]);

}

}

}

else

{

//来到这里,说明了是uri请求指定了目录,而没有指定控制器的情况下。

那么,我们默认当前路由是在当前目录下请求默认的

//控制器和方法。

//下面这个判断只是判断一下$this->default_controller有没有指定方法而已。

if(strpos($this->default_controller,'/')!

==FALSE)

{

$x=explode('/',$this->default_controller);

$this->set_class($x[0]);

$this->set_method($x[1]);

}

else

{

$this->set_class($this->default_controller);

$this->set_method('index');//没有的话就默认为index方法。

}

//Doesthedefaultcontrollerexistinthesub-folder?

//如果连默认控制器都不存在的话,就无语了,说明uri打算请求这个目录的默认控制器,结果没有这个默认控制器,那暂时

//返回个空数组。

(但是看清楚,上面已经$this->set_class()了,说明即使没有,我们也已经把默认控制器的名字算

//是确定下来先)

if(!

file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php'))

{

$this->directory='';

returnarray();

}

}

//能够有命来到这一步,是说明的确是某个目录下找到了控制器,或者是找到了定义的默认控制器。

//但是注意,这个$segments返回的“段”信息都是不包括目录的。

它是一个数组形式,第一个元素是控制器名。

//例如:

array('acontroller'

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1