yii2正确使用 url rule

2017-12-15 邪哥

关于Yii2 配置文件中路由规则的使用说明 (基于yii2.0.12)

看到挺多同学在问URL路由规则的问题,本人之前也踩过些坑,所以感觉有必要整理一下,方便后来者

PS: 首先明确一下,请确保你的框架版本 >=2.0.12,老版本在URL生成逻辑中存在一些bug。

如果你的项目不方便直接更新框架版本,可以单独更新  vendor/yiisoft/yii2/web/UrlRule.php  文件。

详细的可以查看 `yii\web\UrlRule` 类的源码 

@see github.com/yiisoft/yii2/issues/10970

另外网上大部分问答,似乎都是在重复官方文档中的配置说明,不解决实际问题。所以重新整理还是有必要的,也希望各位看官能有所收获。


 回到正题,关于url rule的配置及使用 

配置代码段


//...
        '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 


完。

手动测试排版,如有纰漏,欢迎指正。

芝麻绿豆 Yii2

(0) (2156)

发表评论: