yii错误页需同时配置erroraction路由、控制器动作和视图路径三者,且仅在yii_debug=false时生效;api错误须另写json格式actionerror并手动设状态码与返回数组。

Yii 框架的错误页面不能靠“写个视图就生效”,必须配对 errorAction 路由 + 控制器动作 + 视图路径三者,缺一不可;开发环境(YII_DEBUG=true)下会强制显示调试页,此时任何自定义配置都无效。
errorAction 配置只在 components.errorHandler 里生效
很多人把 errorAction 写在控制器的 actions() 或 behaviors() 里,结果完全没反应——因为 Yii 的错误分发流程压根不走那里。
必须在 config/web.php 的 components 下配置:
'errorHandler' => [
'errorAction' => 'site/error',
],
-
errorAction值只能是controller/action格式,不能带模块前缀(如admin/site/error会失败,得用'route' => 'admin/site/error') - 对应控制器方法(如
SiteController::actionError())必须存在,且要返回$this->render('error'),不能只是throw new Exception - 如果控制器是
errors,那视图路径就得是@app/views/errors/error.php,不是随便命名的
site/error 动作里怎么区分 404 和其他错误
errorAction 是统一入口,它不自动按 HTTP 状态码分流。想让 404 显示单独页面,得在动作里手动判断异常类型:
public function actionError()
{
$exception = Yii::$app->errorHandler->exception;
if ($exception instanceof \yii\web\NotFoundHttpException) {
return $this->render('error-404');
}
return $this->render('error');
}
- 别依赖
$this->getView()->context或Yii::$app->getResponse()->getStatusCode()判断状态码——它们在 errorAction 中可能不准或未设置 - 视图中能直接用
$exception、$statusCode、$name、$message四个变量,不用额外传参 - 若想在视图里快速确认是否真进来了,可临时加
<?php var_dump($exception->getMessage()); ?>
API 接口要返回 JSON 错误格式,不能只改视图
默认的 errorAction 渲染的是 HTML 页面,对 API 来说就是灾难:前端收到一堆 HTML 标签,或者响应被截断。
正确做法是另起一个纯 JSON 的错误动作(比如 api/error),并在其中手动设状态码和返回数组:
public function actionError()
{
$exception = Yii::$app->errorHandler->exception;
if ($exception !== null) {
Yii::$app->response->setStatusCode($exception->statusCode ?: 500);
return [
'code' => $exception->getCode() ?: 50000,
'message' => $exception->getMessage(),
'data' => [],
];
}
}
- 返回数组即可,Yii 会自动序列化为 JSON(前提是请求头含
application/json或已设responseFormat = Response::FORMAT_JSON) -
$exception->statusCode对HttpException子类有效,但普通Exception是null,必须兜底 - 千万别在
actionError里再throw异常,否则触发二次错误处理,可能死循环
开发环境 YII_DEBUG=true 时所有自定义都失效
这是最常被忽略的一点:只要 YII_DEBUG 为 true,Yii 就会跳过 errorAction,直接渲染带堆栈的调试页。你改了视图、换了路由、重写了动作,全白搭。
验证是否真走自定义流程,只有一招:
- 临时把
YII_DEBUG设为false(比如在web/index.php里加defined('YII_DEBUG') or define('YII_DEBUG', false);) - 或者部署到生产环境再测——本地开发时,想看自定义页就得关调试模式
真正上线前务必确认 YII_DEBUG=false 且 errorAction 配置完整,否则用户看到的还是白屏或调试信息泄露。











