yii异常处理由yii\web\errorhandler统一接管,需在config/web.php的components中配置erroraction指向site/error,且生产环境必须关闭yii_debug才能生效。

Yii 的异常处理不是靠“捕获再 try-catch”兜底,而是由 yii\web\ErrorHandler 统一接管 —— 你改配置、换类、调方法,核心都在它身上。不配对 errorAction,或没关掉 YII_DEBUG,自定义页面就永远出不来。
errorAction 配置在哪写才生效
只在 config/web.php 的 components 里写才管用,其他地方全是白搭。
-
'errorHandler' => ['errorAction' => 'site/error']是最低要求,漏掉整个键值对就走默认调试页 -
site/error中的site是控制器 ID,对应@app/controllers/SiteController.php;error是动作名,必须是actionError() - 如果用了模块(比如
admin),要写成'route' => 'admin/site/error',否则路由找不到 - 开发期
YII_DEBUG = true时,哪怕配了errorAction也会强制显示调试页 —— 这不是 bug,是设计行为
renderException() 为什么不执行或返回空白
重写 renderException() 后页面空白,90% 是因为没走完 Yii 的渲染链路。
- 必须显式调用
parent::renderException($exception),否则不会触发errorAction对应的视图渲染 - 不能在方法里
echo、print_r或exit,得返回字符串(例如return $this->render('error-500', [...])) -
ParseError、Fatal Error不进renderException(),它们走handleFatalError(),这个也得重写 - 响应已被输出(比如前面有
var_dump、ob_flush或调试工具条提前写入)时,再返回内容也会被吞掉
404 和 500 怎么分开展示
别指望 HTTP 状态码判断,得看异常类型 —— Yii 的 NotFoundHttpException 和普通 Exception 是两类东西。
- 在
SiteController::actionError()里检查:if ($exception instanceof \yii\web\NotFoundHttpException),然后return $this->render('error-404') - 或者在自定义
CustomErrorHandler::renderException()里提前分发,比在视图里if更干净 - 别用
Yii::$app->response->getStatusCode()判断,这个值在错误流程中不可靠,且 404/500 都可能返回 500(比如未捕获异常抛在 404 之后) -
error-404.php和error-500.php都得放在@app/views/site/下,文件名必须匹配render()调用里的参数
API 场景下怎么统一返回 JSON 错误格式
HTML 错误页对 API 完全无用,errorAction 返回的必须是纯数组,让 Yii 自动序列化。
- 在
SiteController::actionError()里直接return ['code' => 500, 'message' => $exception->getMessage()],不要render() - 状态码映射要手动做:
$statusCode = $exception->statusCode ?: 500,再设Yii::$app->response->statusCode = $statusCode - 对
HttpException子类(如BadRequestHttpException)可建$codeMap = [400 => 10001]表,避免一堆if - 千万别在
actionError()里再throw新异常,会递归进入错误处理器,最终 500 崩溃
最常被忽略的是环境开关:生产环境必须关 YII_DEBUG,否则所有自定义都无效;而 errorAction 没配对、actionError() 方法不存在、视图路径拼错这三处,占了线上异常页面不显示的 80% 原因。











