Big Bug Ban

兴趣 践行 创新

MVC in php — 路由(Router)

 

前面提到了控制器(C)和视图(V)

依据我们前面介绍的方式,主入口是index.php

不是通过对物理文件的映射来访问,而通过用户输入的URL来实现访问,依据用户输入的url指定到对应的控制器上。

这个部分就叫路由器(Router),它的存在目的就是实现单一入口

一个超级简陋的的url分发器如下

include $ROOT . "/action/" . $_GET[‘action’] . ".inc.php";

没错~ 这一句话也可以看做是一个router。它实现了单一入口

但是它存在什么问题呢?

第一,它不安全

如果我传入index.php?action=../../../../../../home/bzw/1

我的1.php将被包含在你的项目中运行,这个是一个本地文件包含漏洞【http://www.51cto.com/html/2005/1128/12370.htm

第二,参数受限

一般用这种方式只能route到单个文件,不能针对类和类的方法进行映射

所以,一般采用这种方式实现的比较少,大多通过url mapping映射到类上

首先,我们来看看java的servlet实现方式

<servletmapping>
    <servletname>dispatcher</servlet-name>
    <urlpattern>*.do</url-pattern>
</servlet-mapping>

它把所有的*.do映射到servlet名称为dispatcher的上面,然后再由这个dispatcher通过反射,动态代理等方式映射到响应的控制器上。

在php中,一般采用有三种方式进行URL映射

第一种,也是比较容易接受的就是上面的通过url参数进行映射的方式,不过呢,一般是两个参数,分别代表控制器类和方法

比如index.php?c=index&m=index

映射到的是index控制器的index方法

第二种,是通过url-rewrite的方式,这样的好处是可以实现对非php结尾的其他后缀进行映射,当然通过rewrite也可以实现第一种方式,不过纯使用rewrite的也比较常见

一般需要配置apache或者nginx的rewrite规则

<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteBase /
	RewriteRule ^index\.php$ - [L]
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule . /index.php [L]
</IfModule>


通过这种方式可以把所有请求转发到index.php上,我们常用的wordpress就是这样的方式。然后程式再通过QUERY_STRING进行解析,映射和转发到响应的控制器上。

第三种,就是通过pathinfo的方式,所谓的pathinfo,就是形如这样的url  xxx.com/index.php/c/index/aa/cc,apache在处理这个url的时候会把index.php后面的部分输入到环境变量$_SERVER[‘PATH_INFO’],它等于/c/index/aa/cc

然后我们的路由器再通过解析这个串进行分析就可以了,后面的部分放入到参数什么地方的,就依据各个框架不同而不同了。很多框架都喜好使用这种方式,但是这种方式缺有很多先天性的因素。

我知道的有两个,第一个是如果你的php工作在cgi或者fastcgi模式下,默认是没有传入PATH_INFO的,环境变量里面也没有这个值,需要对服务器进行配置,而且要注意php的配置里面有个cgi.fix_pathinfo是不是开启了,如果开启了会导致fastcgi的一个解析漏洞【http://www.80sec.com/nginx-securit.html】,

另外一个就是比如你的页面url是xxx.com/index.php/c/index/aa/cc  请小心图片,js目录的位置,有部分浏览器会认为你的当前路径在xxx.com/index.php/c/index/aa/下面,如果你的图片是a.jpg。那么它会去查找xxx.com/index.php/c/index/aa/a.jpg,导致图片和其他资源加载失败。

当然,大多数框架三者都是同时支持的。但是在路由过程中为什么要用类而不用文件来表示控制器呢?之后继续分解~

Written by princehaku

7月 4th, 2012 at 11:12 下午

Posted in php

Tagged with

with 3 comments

3 Responses to 'MVC in php — 路由(Router)'

Subscribe to comments with RSS or TrackBack to 'MVC in php — 路由(Router)'.

  1. [熊猫]

    熊猫

    5 7月 12 at 7:00 下午

  2. 通过这种方式可以把所有请求转发到index.php上,我们常用的wordpress就是这样的方式。然后程式再通过QUERY_STRING进行解析,映射和转发到响应的控制器上。这里应该是通过REQUEST_URI进行解析吧。虽然不太明白,但感觉处理URI这样更合理一些。

    ibird

    22 3月 13 at 5:47 下午

  3. 恩 好像确实表述上有点问题 大多数也是用的REQUEST_URI进行解析 然后再按照规则拆分的

    princehaku

    27 3月 13 at 12:40 上午

Leave a Reply