必须同时配置Web服务器和Yii2的urlManager,缺一不可;Web服务器需将美化URL(如/article/123)转发至index.php,Apache用.htaccess启用mod_rewrite并设置AllowOverride All,Nginx用try_files $uri $uri/ /index.php?$args且确保$document_root指向web/目录;Yii2中需同时设enablePrettyUrl=>true和showScriptName=>false,并配置有效rules。

必须同时改 Web 服务器配置和 Yii2 的 urlManager,缺一不可。只配框架或只配服务器,都会 404。
Web 服务器转发请求到 index.php
美化后的 URL(比如 /article/123)不对应真实文件,得让 Apache 或 Nginx 把所有非静态资源请求都转给 index.php 处理。
- Apache:确认
mod_rewrite已启用,在项目web/目录下放.htaccess,内容至少包含:RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php - Nginx:在
location /块里用try_files,别用过时的if (!-e $request_filename):location / { try_files $uri $uri/ /index.php?$args; }注意$document_root要正确指向web/目录,否则SCRIPT_FILENAME会错。 - 常见错误:Nginx 配置里漏掉
?$args,导致 GET 参数(如?page=2)丢失;Apache 下.htaccess权限被禁(AllowOverride None),规则根本不执行。
Yii2 urlManager 基础配置
urlManager 必须显式启用美化,并关闭入口脚本名显示,否则所有自定义规则都不生效。
- 在
config/web.php或config/main.php的components里加:'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [], ], -
'enablePrettyUrl' => true和'showScriptName' => false必须同时为true,少一个,Url::to(['site/about'])就还是输出/index.php?r=site%2Fabout。 - 如果想加伪后缀(如
/article/123.html),加'suffix' => '.html'即可,但注意静态资源(.css、.js)也会被匹配,需在 Web 服务器规则里确保它们优先被真实文件响应。
写可匹配又可生成的路由规则
规则 key 是请求路径模板,value 是目标路由字符串;要让 Url::to() 正常工作,不能把 value 写成数组。
- 基础写法:
'article/<id:>' => 'article/view'</id:>,访问/article/123会进ArticleController::actionView(),且Url::to(['article/view', 'id' => 123])会生成/article/123。 - 参数正则必须明确:
<id:></id:>比<id></id>更安全,后者默认匹配[^/]+,容易误匹配斜杠或空值。 - 顺序很重要:泛化规则(如
'<controller>/<action>' => '<controller>/<action>'</action></controller></action></controller>)必须放在具体规则之后,否则/article/123会被前面那条先吃掉,永远匹配不到你的article/<id:></id:>。 - 别漏掉
class声明:如果要用正则、默认值等高级功能,得显式指定['class' => 'yii\web\UrlRule'],否则 Yii 默认用简单字符串匹配,<id:></id:>不起作用。
调试时最该看的三个地方
URL 美化失败,90% 的问题出在这三处,而不是规则本身写得有多复杂。
- 检查
urlManager是否真的加载了:在控制器里var_dump(\Yii::$app->urlManager->enablePrettyUrl);,不是true就白配。 - 用
curl -I http://yourdomain/article/123看返回状态码,如果是 404 且没进index.php,说明 Web 服务器转发没生效;如果是 200 但内容不对,才查框架路由。 - 开启
enableStrictParsing(临时):'enableStrictParsing' => true,能让不匹配任何规则的请求直接报 404,避免被 fallback 规则静默吞掉,方便定位漏匹配。
真正麻烦的从来不是怎么写规则,而是 Web 服务器和框架两层之间谁没接上信号——转发没通、配置没载入、顺序被颠倒,这些点不盯死,再漂亮的规则也跑不起来。


















