Yii2 REST接口错误默认不JSON显示,因ErrorHandler仅在YII_DEBUG=false且请求含Accept:application/json或为AJAX时才走JSON分支;curl、Postman等常不带该头,导致500返回HTML页面。

Yii2 REST接口错误默认不 JSON 显示,必须显式接管错误流,否则 500 会返回 HTML 页面、空响应或状态码错乱。
为什么 throw Exception 后前端收不到 JSON 错误
Yii2 的 yii\web\ErrorHandler 默认只在 YII_DEBUG = false 且请求头含 Accept: application/json 或是 AJAX 请求时才走 JSON 分支。curl、Postman、小程序、axios(未显式设 header)多数不带这个头,结果就是 500 页面源码直接吐给前端。
- 不是代码没抛异常,而是异常没被“JSON 化”路径捕获
-
response->format = \yii\web\Response::FORMAT_JSON只影响正常返回,对错误流完全无效 - 直接在 action 里
die(json_encode([...]))会绕过 Yii 错误处理,状态码永远是 200
最稳的配置:单独配 API 模块的 errorHandler
别改全局 errorHandler,避免影响后台页面。在 API 模块(如 modules/api/Module.php)的 init() 里注册:
public function init()
{
parent::init();
Yii::$app->setComponents([
'errorHandler' => [
'class' => 'yii\web\ErrorHandler',
'errorAction' => 'api/error',
],
]);
}
然后在 controllers/ApiController.php 中写 actionError():
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 必须返回数组(Yii 会自动 JSON 化),不能 echo / die / exit
- 手动设状态码:
Yii::$app->response->statusCode = $exception->statusCode ?: 500 - 对非
HttpException(比如Exception),$exception->statusCode是 null,得兜底 - 别再 throw 新异常,否则二次进 error handler,可能死循环
POST JSON 失败时拿不到参数?先确认 JsonParser 是否生效
如果连 400 Bad Request 都没 JSON 化,大概率是请求体根本没解析成功——错误发生在更早阶段,errorHandler 根本没机会介入。
- 检查
config/web.php的components['request']['parsers']是否包含:'application/json' => 'yii\web\JsonParser' - 没配的话,
Content-Type: application/json的 body 会被当 raw string 忽略,框架连参数校验都做不了,直接 400 并返回 HTML 错误页 - 验证方式:打印
Yii::$app->request->getRawBody()能看到原始 JSON,但post()和getBodyParams()为空 → 就是 parser 缺失
自定义业务异常要继承 UserException
用 throw new \Exception('xxx') 或裸 throw new \yii\base\Exception(),会导致 PHP 致命错误页,跳过 Yii 的 errorHandler。
- 客户端错误(如参数错、权限不足):用
throw new \yii\web\BadRequestHttpException('xxx')或throw new \yii\web\ForbiddenHttpException('xxx') - 业务逻辑异常(如“余额不足”“库存已售罄”):继承
\yii\base\UserException,它被ErrorHandler当作客户端错误处理,不会触发 500 页面 - 绝对不要在 action 里用
die()、exit()、echo json_encode()替代异常抛出
真正难调的不是“怎么让错误变 JSON”,而是“错误发生前那一步有没有把请求体正确解析进来”。parser 配错、header 漏传、异常类型选错,三者任一出问题,JSON 错误响应就断在半路。

















