yii2的errorhandler默认不强制返回json,仅在yii_debug=false且请求为ajax或accept头为application/json时才返回json;api项目应通过配置errorhandler组件、设置response格式及手动设状态码来统一json错误响应。

Yii2 中 yii\web\ErrorHandler 默认不返回 JSON?
默认情况下,Yii2 的错误处理器会根据请求头(Accept)决定返回 HTML 还是 JSON,但实际项目里经常发现 API 请求 500 时还是吐出 HTML 错误页——根本原因是:Yii2 的 ErrorHandler 只在 YII_DEBUG = false 且请求是 AJAX 或 Accept: application/json 时才走 JSON 分支,而多数 API 客户端(如 curl、Postman)并不自动带这个 header。
实操建议:
- 强制所有 API 请求走 JSON 错误响应,别依赖客户端 header
- 在入口文件
web/index.php中,于(new yii\web\Application($config))->run();前插入:Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) { if (strpos(Yii::$app->request->getContentType(), 'application/json') !== false || Yii::$app->request->isAjax) { Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; } }); - 更稳妥的做法是:为 API 模块单独配置
errorHandler组件,覆盖errorAction并指定 JSON 格式
怎么让 yii\web\HttpException 和普通异常都统一成 JSON?
默认 HttpException(如 NotFoundHttpException)会被 ErrorHandler 特殊处理,但自定义抛出的 Exception 可能直接触发 PHP 致命错误页面。关键点在于:必须让所有异常最终由 Yii 的 ErrorHandler 捕获,而不是被 PHP 默认错误处理器接管。
实操建议:
- 确保没在代码中用
die()、exit()或裸throw new Exception()绕过 Yii 异常流程 - 在控制器中主动抛异常时,优先用
throw new \yii\web\BadRequestHttpException('xxx')而非原生Exception - 若需抛自定义业务异常,继承
\yii\base\UserException(它不会触发 500 页面,而是被当成客户端错误处理) - 在
config/web.php中显式配置:'errorHandler' => [ 'errorAction' => 'site/error', ],并确保SiteController::actionError()返回的是Response::FORMAT_JSON
site/error 动作里怎么组织 JSON 结构才不踩坑?
很多人直接在 actionError() 里 return ['code'=>500, 'msg'=>'xxx'],结果发现 status code 是 200 ——因为 Yii 默认把 JSON 响应设为 200,异常状态码得手动设。
实操建议:
- 必须手动设置响应状态码:
$exception = Yii::$app->errorHandler->exception; if ($exception !== null) { Yii::$app->response->setStatusCode($exception->statusCode ?: 500); } - 避免直接输出
$exception->getMessage(),生产环境要屏蔽敏感信息,用YII_DEBUG ? $exception->getMessage() : 'Internal server error' - 推荐结构保持简洁:
{ "code": 404, "message": "Not found", "data": null },别塞 trace、file、line 等调试字段到线上响应里 - 如果用了 RESTful 模块(
yii\rest\Controller),优先复用其serializeData()逻辑,别另起一套
API 和 Web 页面共存时,怎么避免 JSON 错误污染 HTML 页面?
一个项目既有后台管理页(HTML),又有 API 接口(JSON),最容易出问题的是:某个 AJAX 请求触发了异常,ErrorHandler 返回了 JSON,但前端 JS 没正确处理,反而把 JSON 当 HTML 插进 DOM,页面就乱了。
实操建议:
- 不要全局改
response->format,而是按模块或路由前缀区分:if (preg_match('/^\/api\//', Yii::$app->request->pathInfo)) { Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; } - 给 API 请求加统一前缀(如
/api/v1/),并在UrlManager中配置rules将其导向专用模块,该模块独立配置errorHandler - 前端务必检查响应 Content-Type,再决定如何解析;后端可在 JSON 响应头里加
X-Response-Format: json辅助判断
真正麻烦的不是写几行 JSON 返回逻辑,而是异常路径是否全程受控——从 throw 的那一刻,到 response 发出去,中间任何一个环节绕过 Yii 的异常流,格式就不可控了。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











