Yii路由匹配按rules数组顺序逐条尝试,首条匹配即生效,后续规则不执行;通配符规则须置末尾,正则应加^$锚点,host/suffix等条件独立判断且不继承。

Yii 路由规则匹配是按 rules 数组顺序逐条试的
Yii 的 URL 解析不是“最精确匹配”,而是从上到下扫描 rules 数组,遇到第一条能匹配上的就直接用,后面规则完全不看。这意味着顺序就是优先级。
常见错误现象:404 出现在你明明写了规则的情况下;或者某个 URL 被错误地路由到不该去的控制器——大概率是更宽泛的规则挡在了前面。
- 通配符规则(如
'<strong><controller:\w+>/<action:\w+></strong>' => '<strong><controller>/<action></strong>')必须放在数组末尾,否则会吃掉所有更具体的规则 - 带固定前缀的规则(如
'api/v1/user/<id:\d+>')要放在泛型规则之前 - 正则中用了
.*或没加锚点^$的规则容易过度匹配,建议用^和$显式限定边界
带参数的路由规则必须写全路径段,不能靠 fallback 补充
Yii 不会自动把未声明的路径段塞进 $_GET,也不会尝试“补全”缺失的命名参数。匹配失败就是失败,不会降级到下一条规则——除非你明确写了可选参数或使用通配符。
使用场景:想支持 /post/123 和 /post/123/edit 两种格式,但又不想写两条规则?不行,必须分开定义,或用正则合并。
-
'post/<id:\d+>' => 'post/view'—— 只匹配两段 -
'post/<id:\d+>/edit' => 'post/update'—— 必须显式写出第三段 - 如果写成
'post/<id:\d+><action:\w+>',实际会匹配/post/123edit(无分隔符),不是你想要的
host、scheme、suffix 这些选项只影响当前规则,不继承也不叠加
每个规则的 host、scheme、urlSuffix 是独立判断条件。哪怕其他规则没设 urlSuffix,当前规则加了 'urlSuffix' => '.html',那它就只匹配带 .html 的请求,不带的直接跳过——不会因为别的规则没限制就“默认通过”。
性能影响:这些额外判断会略微增加匹配开销,尤其是 host 做字符串比对时。开发期可以多用,线上高频路由建议精简条件。
-
'host' => 'admin.example.com'和'host' => 'api.example.com'必须是不同规则,不能合并 -
'urlSuffix' => ''(空字符串)≠ “不限制后缀”,它等价于要求后缀为空,即不接受任何后缀 - 想同时支持带/不带
.html?得写两条规则,或改用UrlManager::addRules()动态注册
调试路由匹配过程只能靠日志或临时打点,没有内置 trace 工具
Yii 不提供类似 Laravel 的 php artisan route:list 或匹配 trace 输出。你看到 404,没法直接知道“卡在哪条规则”,只能靠人工模拟或加日志。
实操建议:在 UrlManager::parseRequest() 入口处加一行 Yii::debug("trying rule: " . json_encode($rule)),配合开启 debug 模式查看。
- 别依赖浏览器地址栏直接测试——重定向、HTTPS 强制、Nginx rewrite 都可能提前改写 URL,导致和 PHP 看到的不一致
- 用
curl -v http://localhost/post/123看原始响应头和 body,排除前端干扰 - 规则里用了
\w+却传了中文或短横线?记得改成[\w\-]+,否则静默失败
最常被忽略的是:规则数组本身可能被多个配置文件 merge 覆盖,比如 main-local.php 里追加了一条规则,却没注意 main.php 里已有同名 key 被覆盖。检查最终生效的 Yii::$app->urlManager->rules 值,比猜强得多。



















