yii的404由errorhandler统一接管,必须在config/web.php的components中配置erroraction;抛notfoundhttpexception是推荐做法,setstatuscode易失效;需区分框架层与web服务器层404。

Yii 的 404 不是靠“设置页面路径”就能生效的,它由 errorHandler 统一接管,但只在应用级组件配置中起作用;写在控制器、行为或路由里全无效。
errorAction 配置必须放在 config/web.php 的 components 里
很多人把 'errorAction' => 'site/error' 塞进控制器的 actions() 或 behaviors(),这完全不触发错误分发流程。Yii 的错误捕获是全局的,只认 components['errorHandler'] 这个位置。
- 正确写法:
'components' => [ 'errorHandler' => [ 'errorAction' => 'site/error', ], ] - 开发环境(
YII_DEBUG = true)下该配置被强制忽略,会显示调试页 —— 别在本地测试时怀疑配置错了 - 如果用模块(如
admin),想让错误页走模块内逻辑,得写成'route' => 'admin/site/error',否则仍按应用级路由找视图
视图文件名和路径是硬编码的,不能随便改
Yii 默认查找 @app/views/site/error.php,这个路径不是约定俗成,而是由 errorAction 的 controller 部分(site)和固定文件名 error.php 共同决定的。你写成 error-404.php 或放错目录,它就直接 fallback 到默认 HTML 错误页。
- 视图里可直接用
$exception和$statusCode变量,不用额外传参 - 要区分 404 和其他错误?在
SiteController::actionError()里判断:if ($exception instanceof \yii\web\NotFoundHttpException) { return $this->render('error-404'); } - 别依赖
Yii::$app->response->getStatusCode()—— 在actionError中它可能还没被正确设置
404 应该用抛异常,而不是 setStatusCode
在控制器里调 Yii::$app->response->setStatusCode(404) 很容易失效,因为响应头可能已被发送,或者后续渲染覆盖了状态码。Yii 推荐做法是直接抛出 NotFoundHttpException。
- 查不到数据时:
if (!$model) { throw new \yii\web\NotFoundHttpException('ID 不存在'); } - REST 场景下,这个异常会自动转成 JSON 响应,含
"name": "Not Found"字段 - 如果非要用
setStatusCode,必须确保它出现在render()、echo、任何输出之前,且没其他组件(比如调试工具条)提前触发了输出
Web 服务器配置错误会导致“假 404”
你以为是 Yii 报 404,其实可能是 Nginx/Apache 根本没把请求转发给 index.php。典型表现:访问 /gii 或 /site/about 直接 404,但 /index.php/site/about 能打开。
- Nginx 必须配
try_files $uri $uri/ /index.php?$args;,缺$args会导致 GET 参数丢失 -
SCRIPT_FILENAME要用$realpath_root而非$document_root,尤其在符号链接部署时 - Apache 需确认
AllowOverride All已启用,且mod_rewrite已加载 - urlManager 开启了
enablePrettyUrl却没关showScriptName,也会导致所有非index.php开头的 URL 被 Web 服务器拦截
真正难调的不是怎么写 error.php,而是搞清当前这个 404 是 Yii 框架层抛的,还是 Web 服务器层拦的 —— 前者看日志和 $exception,后者得查 Nginx error_log 或 Apache access_log。











