Yii2自定义错误页面生效的前提是请求必须进入框架,Nginx/Apache不得提前拦截404;errorAction必须配置在config/web.php的components中且位于urlManager之前;YII_DEBUG=true时该配置被忽略;视图路径为@app/views/{controller}/error.php,文件名严格为error.php;API需强制response格式为JSON并配对应errorAction。

Yii2自定义错误页面能生效,前提是请求必须进到框架里——如果Nginx/Apache直接返回404,site/error根本不会被调用。
errorAction 配置必须写在 components 里
很多人把 'errorAction' => 'site/error' 错误地塞进控制器的 actions() 或行为中,这完全无效。它只在应用级组件配置中起作用:
- 打开
config/web.php,确保在'components'数组内有如下配置(且位置要在urlManager之前):
'errorHandler' => [
'errorAction' => 'site/error',
'maxSourceLines' => 15,
'maxTraceString' => 512
],
- 若用了模块(如
admin),想让错误页走模块内控制器,得配'route' => 'admin/site/error',否则默认只认应用根命名空间下的SiteController -
YII_DEBUG = true时,该配置会被强制忽略,直接显示调试页——这是预期行为,不是配置失败
视图文件名和路径有硬性规则
Yii2 不会自动匹配 error-404.php 或 errors/500.php,它只按固定逻辑找:
- 视图路径是
@app/views/{controller}/error.php,其中{controller}就是errorAction中斜杠前的部分(比如'site/error'→@app/views/site/error.php) - 文件名必须叫
error.php,大小写敏感;error-404.php这类文件仅在yii\web\ErrorAction内部被条件加载,但前提是主视图error.php存在且主动调用$this->render('error-404') - 视图中可直接用
$exception变量,但注意:它可能为null(比如某些 PHP 致命错误未被捕获),建议先判空
404 页面不显示?先看请求有没有进 Yii
最常见现象:访问不存在路由,浏览器只看到 Nginx 默认 404 页,error.php 完全没执行。原因几乎全是 Web 服务器配置问题:
- Nginx 必须用
try_files $uri $uri/ /index.php?$args;,不能只写fastcgi_pass后就结束 - Apache 要确认
.htaccess生效,且包含标准重写规则(如RewriteRule ^(.*)$ index.php?r=$1 [QSA,L]) - Yii 的
urlManager必须启用美化:'enablePrettyUrl' => true,否则/post/123这类路径压根不会路由,直接 404 - 验证方法:临时在
web/index.php开头加file_put_contents('/tmp/hit.log', 'ok');,访问一个不存在路径,看日志是否生成
API 返回 HTML 错误页?别依赖 Accept 头
客户端不带 Accept: application/json 时,Yii2 默认仍返回 HTML 错误页,这对 API 是灾难性的。解决方式不是改视图,而是接管响应格式:
- 在
config/web.php的'components'中,给response加强制格式:
'response' => [
'format' => \yii\web\Response::FORMAT_JSON,
'charset' => 'UTF-8',
],
- 同时确保
errorHandler的errorAction指向一个纯 JSON 渲染动作(比如'api/error'),并在该 action 中手动设状态码:Yii::$app->response->setStatusCode($exception->statusCode ?? 500) - 避免在错误视图里调用任何可能触发新异常的代码(如未注册的 asset bundle、未初始化的组件),否则会二次崩溃,fallback 到白屏
真正容易被忽略的是:错误视图里的 $exception->getTraceAsString() 在生产环境绝对不能输出,哪怕只是调试时临时加的 var_dump,上线前必须删掉——路径、数据库账号、密钥都可能从堆栈里泄露出来。


















