- ThinkPHP实战
- 夏磊
- 1205字
- 2020-11-28 18:26:52
3.2 ThinkPHP的路由
3.2.1 路由模式
ThinkPHP的路由支持以下四种模式:
● 普通模式
● pathinfo模式
● rewrite模式
● 兼容模式
接下来通过一个具体的场景来分析这四种路由模式,假设用户访问Home模块的Index控制器的index方法,这四种模式下的URL如下:
● 普通模式:http://www.example.com/index.php? m=home&c=index&a=index
● pathinfo模式:http://www.example.com/index.php/home/index/index
● rewrite模式:http://www.example.com/home/index/index
● 兼容模式:http://www.example.com/index.php? s=home/index/index
可以看到普通模式和兼容模式可以归类到动态URL中,pathinfo和rewrite模式可以归类到伪静态模式中。rewrite模式和pathinfo模式的区别在于前者没有index.php,有HTTP基础的读者可能有些不理解,如果按照静态页面的处理方式,rewrite模式下Web服务器会前往Web目录下的home/index/index查找默认首页,如果存在则发送给浏览器,否则发送404错误页面。
接下来可以进行测试,观察这四种URL在浏览器中的实际情况,请将www.example.com替换为相应的Web目录(笔者的为http://localhost/thinkphp-inaction)。
在Web目录下新建文件夹chapter-3,按照第2章的方法新建入口文件,并且在浏览器访问使ThinkPHP初始化。
编辑Application/Home/Controller/IndexController.class.php,内容如下:
<? php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index() { echo 1; } }
文件内容很简单,只要浏览器输出“1”证明访问home/index/index成功。打开浏览器分别测试普通模式(见图3-1)、pathinfo模式(见图3-2)和rewrite模式(见图3-3)。

图3-1

图3-2

图3-3
可以看到,rewrite模式下,已经访问不到home/index/index了,观察URL发现,Web服务器在home/index/index目录下查找默认文件了。这时候就需要对Web服务器进行URL重写设置。
在chapter-3下级目录新建文件“.htaccess”,文件无名称,扩展名为“htaccess”,该文件为Apache服务器的分布式配置文件(通俗点说,就是每个站点可以单独设置,互不影响),文件结构如图3-4所示。

图3-4
文件内容如下:
RewriteEngine on RewriteCond %{REQUEST_FILENAME} ! -d RewriteCond %{REQUEST_FILENAME} ! -f RewriteRule ^(.*)$ index.php/$1 [L]
文件第1行:打开重写引擎。
文件第2行和第3行:如果请求文件不是目录而且不是文件(证明服务器上没有该请求文件或请求目录)。
文件第4行:将所有请求重定向到当前目录下的index.php文件,“L”代表如果该规则成功处理,则不继续处理下一条规则。
以http://localhost/thinkphp-inaction/chapter-3/home/index/index为例,由于服务器上并不存在home/index/index目录,故Apache将请求参数“/home/index/index”全部传给chapter-3/index.php文件处理。
打开浏览器刷新,可以看到如图3-5所示界面。

图3-5
最后则是兼容模式的测试,结果如图3-6所示。

图3-6
3.2.2 路由配置
要使用ThinkPHP的路由功能,只要Web服务器支持除普通模式外的任何一种模式即可,前提是在公共(或模块)配置文件中启用路由功能。
编辑Application/Common/Conf/config.php,内容如下:
<? php /** * config.php */ return array( 'URL_ROUTER_ON' => true );
接下来就是配置路由规则了,在模块的配置文件中使用URL_ROUTE_RULES参数进行配置,配置格式为数组,一个元素就是一个路由规则,编辑Application/Home/Conf/config.php,内容如下:
<? php /** * config.php */ return array( 'URL_ROUTE_RULES' => array( 'posts/:year/:month/:day' => 'Index/index', 'posts/:id' => 'Index/index', 'posts/read/:id' => '/posts/:1', ), );
打开浏览器访问http://localhost/thinkphp-inaction/chapter-3/home/posts/2015/01/01,结果如图3-7所示。

图3-7
ThinkPHP已经将请求地址路由到Application/Home/Controller/IndexController.class.php的index方法中去了。
为了测试一下路由图3-7的结果是否是ThinkPHP路由导致的,编辑Application/Common/Conf/config.php文件,内容如下:
<? php /** * config.php */ return array( 'URL_ROUTER_ON' => false );
刷新浏览器,可以看到如图3-8所示结果。

图3-8
路由定义的一般规则是:“路由表达式”=>“路由地址和参数”或者array(“路由表达式”,“路由地址”,“传入参数”)。
“路由表达式”指“以何种规则”匹配浏览器中的地址,如果匹配成功,系统将在处理请求的同时把“传入参数”(如果有配置)传给指定的动作。
ThinkPHP的路由规则采用顺序遍历方式进行,只要成功匹配一条匹配的路由,则终止继续匹配。
路由表达式支持规则路由、正则路由、静态路由。
1.规则路由
'posts/:year/:month/:day' => 'Index/index',是一个典型的规则路由,通过“:”进行参数匹配,如果匹配成功,则将该位置的参数传给指定的动作。
编辑Application/Common/Conf/config.php文件,将“false”更改为“true”,编辑Application/Home/Controller/IndexController.class.php,内容如下:
<? php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index() { echo "year:".$_GET['year'].", month:".$_GET['month'].",day:".$_GET['day']; } }
刷新浏览器,可以看到如图3-9所示结果。

图3-9
ThinkPHP已经将URL地址中的各项参数传给相应的动作,如果是未启用路由的状态,需要获取year、month、day参数就必须访问形如http://localhost/thinkphp-inaction/chapter-3/index.php? year=2015&month=01&day=01这样的URL才可以。
2.正则路由
顾名思义,正则路由就是利用正则表达式进行“路由表达式”配置,至于正则表达式相关知识,读者可以在网上参考相关资料。
编辑Application/Home/Conf/config.php,内容如下:
<? php /** * config.php */ return array( 'URL_ROUTE_RULES' => array( '/^posts\/(\d{4})\/(\d{2})\/(\d{2})$/' =>'Index/index? year=:1&month=:2&day=1', 'posts/:year/:month/:day' => 'Index/index', 'posts/:id' => 'Index/index', 'posts/read/:id' => '/posts/:1', ), );
请注意:正则路由的最后一个“1”前面没有“:”,固只要URL匹配成功,day参数永远为1。
刷新浏览器,可以看到如图3-10所示的结果。

图3-10
正则路由匹配成功,所以day为1;如果正则路由匹配失败,浏览器将输出12。
接下来将浏览器地址栏URL改为http://localhost/thinkphp-inaction/chapter-3/home/posts/2015/01/010,刷新浏览器,可以看到如图3-11所示的结果。

图3-11
可以看到输出的day为“121”,证明ThinkPHP匹配到了第二条路由,这就是正则路由的优势,最严格的匹配模式,路由配置中正则表达式的最后一个子模式为“(\d{2})”,该正则只匹配两位数字,而请求的URL地址中最后一个参数为3位数字,固正则路由匹配失败,系统使用规则路由。
3.静态路由
静态路由定义中不包含任何动态参数,也不需要遍历路由规则,所以路由效果比前两者高,为了区分前两种路由规则,静态路由采用URL_MAP_RULES进行定义。
编辑Application/Home/Conf/config.php,内容如下:
<? php /** * config.php */ return array( 'URL_ROUTE_RULES' => array( '/^posts\/(\d{4})\/(\d{2})\/(\d{2})$/' => 'Index/index? year=:1&month=:2&day=1', 'posts/:year/:month/:day' => 'Index/index', 'posts/:id' => 'Index/index', 'posts/read/:id' => '/posts/:1', ), 'URL_MAP_RULES' => array( 'site/welcome' => 'Index/index? from=seo' ) );
编辑Application/Home/Controller/IndexController.class.php,内容如下:
<? php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index() { echo $_GET['from']; } }
在浏览器中访问http://localhost/thinkphp-inaction/chapter-3/home/site/welcome,可以看到如图3-12所示结果。

图3-12