Yii2 API中验证失败需统一返回JSON格式,如{"code":422,"message":"验证失败","errors":{"field":["错误信息"]}},并设HTTP状态码为422、启用JSON_UNESCAPED_UNICODE防止中文乱码。

Yii2 中 Model 验证失败时,默认会返回 HTML 错误页或空响应,API 场景下必须转为结构清晰、状态一致的 JSON 格式。核心不是改视图,而是统一拦截验证失败路径,并输出标准格式:{"success": false, "data": {"field": ["错误信息"]}} 或更通用的 {"code": 422, "message": "验证失败", "errors": {...}}。
让验证错误自动进入 JSON 响应流
Model 调用 $model->validate() 后若失败,$model->errors 是二维数组(如 ['name' => ['姓名不能为空']] )。但直接 return 它不会触发统一 JSON 格式——除非你已全局设定了 response format 并在控制器中规范返回。
- 在 action 开头强制设格式:
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; - 验证失败时,不要 throw 异常,而应构造明确响应:
return ['success' => false, 'data' => $model->errors]; - 若使用
\yii\rest\Controller,它默认将数组转为 JSON,且 status code 自动为 200;需手动设\Yii::$app->response->setStatusCode(422);表示验证错误
统一处理 422 状态码的异常出口
当调用 $model->save() 失败(内部会 validate),或你在行为/规则中主动调用 addError() 后抛出 \yii\web\UnprocessableEntityHttpException,可让错误统一落入自定义 errorAction。
- 在 config/web.php 的 components 中配置:
'errorHandler' => ['errorAction' => 'api/error'] - 在
ApiCotroller::actionError()中识别 422:if ($exception instanceof \yii\web\UnprocessableEntityHttpException) {<br> return ['code' => 422, 'message' => '参数验证失败', 'errors' => $exception->getMessage() ?: $model->errors];<br>} - 注意:$exception->getMessage() 通常为空,真实 errors 需从上下文模型获取,建议将模型实例存入 exception 的
extra属性或通过 Yii::$app->params 临时传递
避免常见陷阱:空响应、状态码错乱、中文乱码
验证失败返回 JSON 最容易出问题的三个点:
-
状态码仍是 200:即使数据含 error,HTTP 状态码未改,前端 fetch().then() 仍会进 success 分支。务必显式调用
\Yii::$app->response->setStatusCode(422) -
中文被转义成 \uXXXX:检查 response 组件是否配置了
JSON_UNESCAPED_UNICODE,例如:'formatters' => [\yii\web\Response::FORMAT_JSON => ['class' => 'yii\web\JsonResponseFormatter', 'encodeOptions' => JSON_UNESCAPED_UNICODE]] -
返回空内容:可能因提前 echo、var_dump 或调用了
Yii::$app->end();也可能是$model->errors为空数组但没做判空,导致 return [] —— 建议始终包裹一层'data' => $model->errors ?: []
进阶:封装验证失败响应工具方法
在基控制器(如 ApiController)中添加复用方法,减少重复逻辑:
protected function failValidation($model, $message = '参数验证失败') {<br> \Yii::$app->response->setStatusCode(422);<br> return [<br> 'code' => 422,<br> 'message' => $message,<br> 'errors' => $model->errors<br> ];<br>}- 在 action 中直接使用:
if (!$model->validate()) {<br> return $this->failValidation($model);<br>} - 支持自定义字段映射、错误合并、日志记录等扩展点,便于后续对接监控或国际化


















