strictparsing开启后所有路由404,因yii在路由解析阶段即抛出notfoundhttpexception,未进入控制器,故erroraction不触发;根本原因常为urlmanager缺兜底规则、path_info未正确传递或规则前缀不匹配。

strictParsing开启后所有路由都404
直接后果就是 site/index、site/login 全部 404,连带后台入口也打不开。这不是控制器不存在,而是 Yii 根本没机会去匹配路由规则——enableStrictParsing 强制要求每个请求必须精确命中某条 urlManager 规则,否则立刻抛出 NotFoundHttpException。
- 检查
urlManager配置里是否漏了默认规则:比如没配'<controller>/<action>' => '<controller>/index'</controller></action></controller>这类兜底 rule,而只写了'post/<id:>' => 'post/view'</id:>这种窄匹配 - 确认请求 URL 和 rule 的路径前缀是否一致:前端用
frontend/web/入口,但 rule 写的是'admin/<route:>'</route:>,而实际访问的是/site/index,压根不带admin/前缀,必然失败 - 注意大小写和斜杠结尾:rule 是
'api/v1/<action>'</action>,但请求发的是/api/v1/users/(末尾多斜杠),strict 模式下不自动 trim,直接不匹配
关闭 strictParsing 就能访问,但不想妥协
关掉 enableStrictParsing 确实能“恢复可用”,但代价是路由行为不可控——比如 /site/index/extra 这种非法尾缀也会被 fallback 到 site/index,掩盖真实问题。真要保留 strict,得补全规则链:
- 在
urlManager的rules数组最前面加一条通用兜底:'' => 'site/index'(空路径)和'<controller>/<action>' => '<controller>/<action>'</action></controller></action></controller>(标准格式) - 如果用了模块(如
admin),必须显式声明模块内路由:'admin/<controller:>/<action:>' => 'admin/<controller>/<action>'</action></controller></action:></controller:>,不能依赖模块自动解析 - 前后端分离部署时,确保 frontend 和 backend 的
urlManager各自独立配置,别共用同一份 rules —— backend 的 rule 不该处理/user/profile这类前端路径
为什么开了 strict 后 errorAction 也不触发
因为 NotFoundHttpException 是在路由解析阶段抛出的,早于 controller 实例化,所以 errorAction 对应的 SiteController::actionError() 根本不会执行。你看到的不是自定义错误页,而是框架默认的 404 响应体(或 Nginx 的 404)。
- 想让 404 走自定义页面,只能靠 Web 服务器层拦截:Nginx 加
error_page 404 /404.html;Apache 加ErrorDocument 404 /404.html - 或者,在
urlManager里用'404' => 'site/error'这类显式 rule 把 404 路径映射过去(需确保该 rule 在 strict 模式下能被匹配) - 更稳妥的做法:开发期保持
enableStrictParsing => false,上线前用工具扫描所有链接,确认全部命中已定义 rule,再开 strict
容易被忽略的 PATH_INFO 依赖
enableStrictParsing 不是独立开关,它严重依赖 $_SERVER['PATH_INFO'] 是否正确传递。如果 Nginx 没配 fastcgi_split_path_info,PHP 收到的永远是 /index.php,Yii 看不到后续路径,所有 rule 都无法触发,结果全是 404 —— 此时关 strict 也没用。
- 验证方式:在
web/index.php开头加var_dump($_SERVER['PATH_INFO']); die;,访问/site/index,输出应为/site/index,而非空或false - Nginx 必须有这两行(在
location ~ \.php$块内):fastcgi_split_path_info ^(.+\.php)(/.+)$;和fastcgi_param PATH_INFO $fastcgi_path_info; - Windows 下尤其注意:若用
$realpath_root代替$document_root设置SCRIPT_FILENAME,PATH_INFO 可能被截断或清空











