ThinkPHP3.2.3 路由问题

目录
[隐藏]

和大多数MVC框架一样,ThinkPHP 也提供了路由功能。在项目中使用路由,可以让URL更加简洁和优雅,同时也对搜索引擎更加友好。虽然看上去比较简单,但实际使用中还是遇到不少麻烦。

1、ThinkPHP3.2.3 路由

ThinkPHP3.2.3 中的路由功能暂时只支持PATH_INFO 和 兼容URL模式,对于普通模式的URL不支持。正常情况下,看着官方手册上就知道怎么使用路由了,对于不同的形式什么的这里就不再赘述,仅以自己做参考。

官方提到3.2.3版本中,支持全局路由和模块路由,两者唯一的差别在于全局路由需要指明模块。路由的开启及配置路由规则都是在全局或模块的 config.php 的配置文件中。

1.1 看下差别

不使用路由的url:http://host/index.php/Home/Essay/index/153.html

使用路由后的url 可能是这样:http://host/e/153.html  或者 http://host/e_153.html  等等

具体形式由设计的路由表达式来决定。

1.2 路由前准备

光使用路由功能,还达不到上述效果,隐藏index.php 以及 模块名 要另外进行处理。隐藏 index.php 的方法百度就有很详细的答案了。模块名 怎么隐藏呢?很简单,配置下默认模块即可。

ThinkPHP3.2.3 提供了 'MULTI_MODULE','MODULE_ALLOW_LIST','DEFAULT_MODULE' 来对模块进行一个管理。默认 MULTI_MODULE=true,当这个值为false时,必须同时设置 DEFAULT_MODULE。如果是多模块项目,则配置 MODULE_ALLOW_LIST ,然后设置 DEFULT_MODULE 为你的默认模块。如果配置 DEFAULT_MODULE = 'Home', 则在访问 Home 模块时可以不用加模块名,主要也是对前台url进行路由,所以达到了隐藏Home 模块名的作用。

1.3 启用及配置路由

这里使用的是模块路由,所以在 Home/Conf/config.php 中进行如下配置:

      URL_ROUTE_ON = true,    //启用路由

      URL_MODULE = 2,         // 2 表示兼容url模式,可以隐藏index.php

      URL_MAP_RULES = array(    //定义直接映射,也就是静态路由,适用于不需要参数的url

          'test' => 'Test/index',   //访问 http://host/test 实际上访问的是 http://host/Home/Test/index

         'about' => 'Index/about',

      ),

     URL_ROUTE_RULES = array( //动态路由,可以带参数,还能添加额外参数

         '/e\/(\d+)$/'         =>  array('Essay/index?id=:1'),

         'cate/:name/:p '   =>   array('Fenlei/index')

     )

  '/e\/(\d+)$/' 这里是路由表达式,array('Essay/index?id=:1')这个是路由规则。路由表达式就是出现在url中的形式,而路由规则则是实际访问的控制器以及操作。

按官方手册如上配置,应该就可以使用路由功能了,但现实总是不那么顺利的

1.4 遇到的问题及解决

在模块配置文件中,按上路方式设置以后,发现动态路由无效!

例如:访问 http://host/e/5.html  就提示“无法加载控制器e”

          访问 http://host/Essay/5.html  就提示 "无效操作 5 "

开始还比较懵,但仔细想,很明显是配置的路由规则没有生效,所以ThinkPHP 还是按照

     ‘模块名/控制器/操作’这种形式在解析路由,所以就会认为 e 是控制器,5 是一个操作。。。

那到底为什么没生效了,纠结很久后想到用 C函数 获取一下这个配置参数,看看到底有没有。

  var_dump(  C('URL_ROUTE_RULES') ); 

然后就发现,并没有获取到参数值!但是C('URL_MAP_RULES') 又能获取到值,尝试很多方法后还是未能解决。只能动源码了,,

直接在 ThinkPHP 的惯例配置文件 ThinkPHP/conf/covention.php 中设置URL_ROUTE_RULES,在这里配置路由规则后,发现就能用 C 函数获取 ‘URL_ROUTE_RULES’参数的值了,路由功能也能使用了。虽然临时的解决了,但还是没有弄清原因,,,有遇到同样问题的朋友有比较好的解决办法在下方评论或给我留言吧。

2、U方法生成简短路由

ThinkPHP 提供了 U 方法来根据输入的参数生成 URL,使用该方法可以不用管是PATH_INFO模式还是普通模式,U 方法会根据使用的url模式生成对应形式的 URL,但看到很多人说 U 方法没办法生成路由后的URL.

例如:有一条路由规则  'cate/:name' => 'Fenlei/index'

      U('Fenlei/index?name=xxx') 只会生成 index.php/Home/Fenlei/index/name=xxx 的这种url

而不是 cate/xxx 这种简短路由的方式。其实要实现很简单,不过也得改源码。

U 方法的定义在 ThinkPHP/Common/functions.php 中,好好看一下就很清楚 U 方法的实现了,网上有一些修改版本。但可能没有用,其实修改也不难。主要就是获取到定义的路由规则、然后进行遍历,再按照对应的路由表达式进行拼装生成 url 后返回。我自己也写了一下,实现了对于配置了路由规则的能够生成简短路由的目录,但性能什么就没考虑,自己实际也没用,也就不贴了。

3、分页后的简短路由

开始压根没想到分页后的路由问题,但一次测试中,点击分页按钮,发现 url 并没有使用路由功能。

这肯定就是 Page.class.php 的问题了,在生成分页栏的 url 时候使用了U方法来生成的,这个就只能修改 Page.class.php 文件咯,反正前面定制分页栏也修改过。仔细查看会发现如下:

和猜想的一样,直接根据当前操作用 U 方法生成的。再看拼装 a 标签的代码

并没有直接使用 $this->url ,而是调用了 $this->url(page) 这个方法,这个方法干嘛的?看一下:

原来是用页码参数来替代 $this->url 中的占位符'[PAGE]',这和第一张图所示的代码是对应的。

知道了实现后,那要怎么修改呢?Page 类怎么知道我到底要生成什么样的url呢?既然不同页面的url不同,那就传参进来吧,改变下构造函数。。。所做修改如下:

   在构造函数中添加一个url参数,并将该参数赋值给 $this->url,再以该url为基础来生成指定的简短路由!

对于没有传入 $url 的依旧生成完整url

那怎么调用呢?

   假设要生成:http://host/p/2.html 这种分页url,实际上是 http://host/Index/index/p/2.html

    

  其它按这样,只要修改好 url 参数就可以了。当然还得有 路由规则 的支持。不然生成的简短路由肯定是无效的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

To