Url Rules 使用指南 [ 2.0 版本 ]
关于Yii2 配置文件中路由规则的使用说明 (基于yii2.0.12)
看到挺多同学在问URL路由规则的问题,本人之前也踩过些坑,所以感觉有必要整理一下,方便后来者
PS: 也看了挺多站内的问答, 大体上都是在讲一些 yii2官方文档中给出的说明, 说一些基础的配置方法。然而大多数时候并没有讲到实质问题,所以感觉有必要重新归纳整理一番
配置代码段
//...
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'cache' => YII_DEBUG ? false : 'cache',
'suffix' => '.html',
'rules' => [
'pattern' => 'route', //写法1
[
'class' => 'yii\web\UrlRule',//非必要
'pattern' => '',
'route' => '',
'suffix' => '.do',// 优先级高
//...其它
], //写法2
//...
],
],
如上,常见的rule配置有两种方式:
1、 'pattern' => 'route'
的形式
2、 数组的形式,如果数组中不指定使用的类, 默认即是: yii\web\UrlRule::class
下面咱们分开阐述一下这两种方式的使用
//方式1
//适合一些比较简单的路由规则设置,但是如果出现可选参数,可以采用 配置多条规则的方式解决。
//例如,规则如下
'site/test-<a:\w+>-<b:\w+>' => 'site/index',
'site/test-<b:\w+>' => 'site/index',
//测试
echo Url::to(['site/index', 'b'=>'bvalue']);
//输出 /site/test-bvalue.html
//...
//其它同理
当然,如果你的参数比较多,建太多规则显然是不合适的。
另外就是这种多规则并存使用,容易出现混乱。
//假设我定义3条规则
'site/test-<a:\w+>-<b:\w+>' => 'site/index',
'site/test-<b:\w+>' => 'site/index',
'site/test-<a:\w+>' => 'site/index',
//那么在我访问 /site/test-value.html 的时候
// 这个 value 是a的值还是b的值呢?
//为了避免这种问题, 就可能需要把规则修改为如下配置
'site/test-a<a:\w+>-b<b:\w+>' => 'site/index',
'site/test-b<b:\w+>' => 'site/index',
'site/test-a<a:\w+>' => 'site/index',
所以,个人建议在出现多参数,或者参数为可选时,使用数组的形式进行配置。
下面我们看下数组的配置用例
//沿用 上述例子, 注意 这时候 我们只定义下面一个路由规则
[
'pattern' => 'site/test-<a:\w+>-<b:\w+>',
'route' => 'site/index',
],
//先看看
echo Url::to(['site/index','b' => 'bvalue']);
//输出 /site/index.html?b=bvalue
//变成了 带问号的 get传参形式, 这当然不是我们想要的。
//调整rule配置,如下
[
'pattern' => 'site/test-<a:\w+>-<b:\w+>',
'route' => 'site/index',
'defaults' => [ //默认值
'a' => '', //只能是 空字符串
],
],
//新增了 参数默认值的配置
//重新测试 输出 /site/test--bvalue.html
//到这边其实已经满足了我们的基础需求, 但还是不完善的
为什么不完善呢? 可能你也注意到了,上述 样例配置中 //只能是 空字符串
的注释说明.
截止到目前的官方版本,其它默认值还是不支持的。
比如我修改 a 的默认值为 avalue , 测试结果并不是 /site/test-avalue-bvalue.html
而是回到了 /site/index.html?b=bvalue
的状态
这也不是我想看到的结果, 我可能想把 a 的默认值设置为各种 类似 0 - 9 一些约定的 string等等。
那该如何解决呢?
这时候就比较费劲了, 需要修改框架的核心代码,或者扩展自定义一下。
当然个人建议是 继承后做自定义修改。
操作的具体过程我就不赘述了,请确认你知道如何自定义一个组件类,并能理解配置中指定某个组件类的原理。
核心操作说明:
修改yii\web\UrlRule
中 createUrl
方法中 490行附近的代码逻辑
//逻辑流程前有如下的 源码注释,可以参考 进行搜索
// match default params
// if a default param is not in the route pattern, its value must also be matched
也可以参考我修改的类
https://github.com/JeanWolf/plat/blob/master/common/core/UrlRuleWeb.php
测试样例如下:
//rule 样例配置
[
'class' => UrlRuleWeb::class,
'pattern' => 'site/test-<aa:\d+>-<bb:\d+>-<cc:\d+>',
'route' => 'site/index',
'suffix' => '.do', //自定义后缀 可选配置
'defaults' => [
'aa' => 2,
'bb' => '0',
],
],
//测试
echo Url::to(['site/index', 'cc' => 3]);
//输出 /site/test-2-0-3.do
完。
手动测试排版,如有纰漏,欢迎指正。
顺便打个小广告, 个人博客 http://blog.jeen.wang , 欢迎交流切磋。
转载请著名出处。谢谢 :)
Jeen
最后登录:2024-08-16
在线时长:18小时16分
- 粉丝9
- 金钱1120
- 威望190
- 积分3200
共 6 条评论
大神!!!赞一个!!!太实质了,找了好几天了 都没讲到这些
这里还有一个问题 麻烦了:
'rules' => [ [ 'pattern' => 'product', 'route' => 'article/product', ], [ 'class' => common\core\UrlRuleWeb::class, 'pattern' => 'product_<filter_1:\d+>_<filter_4:\d+>_<filter_7:\d+>_<filter_12:\d+>_<page:\d+>', 'route' => 'article/product', 'suffix' => '',//自定义后缀 可选配置 'defaults' => [ 'filter_1' => 0, 'filter_4' => '0', 'filter_7' => 0, 'filter_12' => 0, 'page' => 1 ], ], //写法2 //... ],
第一条规则 ,如果加上,那么第二条规则 就不生效了
第一条规则 加了class你的类 也不行
另外,如果我把第一条规则去掉了,第二条规则也有个问题,就是参数刚刚好 就是defaults里的那些默认值,那么伪静态就失效了
留意下
UrlRuleWeb
自定义类中的createUrl 方法的源码有一部分是根据个人需求定制的
//400 行左右 if ($_default_count == count($this->_paramRules)) { $this->createStatus = self::CREATE_STATUS_PARAMS_MISMATCH; return false; } //这边 个人为了防止 "无参情况下,都使用默认值" 的情况,加了一个判断条件 //根据你的需求 把这个判断条件删除掉 应该就可以满足了 //如果希望两条规则同时使用 ,可以在第一条中指定类名,然后修改这个判断条件如下 if ($_default_count > 0 && $_default_count == count($this->_paramRules)) { $this->createStatus = self::CREATE_STATUS_PARAMS_MISMATCH; return false; } //测试配置如下 [ 'class' => UrlRuleWeb::class, 'pattern' => 'product', 'suffix' => '.do',//自定义后缀 可选配置 'route' => 'article/product', ], [ 'class' => UrlRuleWeb::class, 'pattern' => 'product_<filter_1:\d+>_<filter_4:\d+>_<filter_7:\d+>_<filter_12:\d+>_<page:\d+>', 'route' => 'article/product', 'suffix' => '.html',//自定义后缀 可选配置 'defaults' => [ 'filter_1' => 0, 'filter_4' => 0, 'filter_7' => 0, 'filter_12' => 0, 'page' => 1 ], ], //写法2
由于是根据项目需求定制,难免会有差异
欢迎补充 各种场景下的处理方案 :)
好的 谢谢
新手拜读。