yii3.0项目需统一api响应为标准json格式,须在config/web.php中配置jsonresponseformatter并设置encodeoptions,全局强制format为json,启用contentnegotiator支持多格式,自定义errorhandler确保错误也返回json。

Yii3.0 项目中需让所有 API 接口统一返回标准 JSON 格式,避免前端解析失败、中文乱码、状态码错位或空响应等问题,必须在框架启动阶段完成响应格式器的注册与行为绑定,不能依赖控制器内零散设置。
启用 JsonResponseFormatter 并配置 encodeOptions
Yii3 默认启用 JsonResponseFormatter,但仅当请求路径命中 API 模块(如继承 yii
estController)时才自动生效;裸用 yiiwebController 仍需手动接管。必须在 config/web.php 的 components.response 中显式挂载并补全编码选项。
打开 config/web.php,定位到 'components' => ['response' => [...]] 配置段,在 'class' 同级添加 'formatters' 数组:
复制以下代码,【务必替换原 response 配置中的 formatters 字段,不可追加】:
'formatters' => [<br> 'json' => [<br> 'class' => yiiwebJsonResponseFormatter::class,<br> 'encodeOptions' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,<br> ],<br>],
这一步漏掉 JSON_UNESCAPED_UNICODE,中文字段会变成 u4f60u597d;漏掉 JSON_UNESCAPED_SLASHES,URL 字段里的斜杠会被转义为 /,前端解析可能出错。
强制所有请求走 JSON 响应流程
Yii3 不再默认按 Accept 头协商格式,尤其对 curl、Postman 或未带 header 的前端请求,极易 fallback 到 HTML 格式,导致返回整页错误模板而非 JSON 对象。
方法一:全局拦截(推荐用于纯 API 项目)
在入口文件 web/index.php 中,(new yiiwebApplication($config))->run(); 执行前插入:
Yii::$app->on(yiiaseApplication::EVENT_BEFORE_REQUEST, function ($event) {<br> Yii::$app->response->format = yiiwebResponse::FORMAT_JSON;<br>});
方法二:模块级控制(适用于前后端混合项目)
在 API 模块的 Module.php 中重写 beforeAction():
public function beforeAction($action)<br>{<br> if (parent::beforeAction($action)) {<br> Yii::$app->response->format = yiiwebResponse::FORMAT_JSON;<br> return true;<br> }<br> return false;<br>}
注意:【此方法必须在模块类中定义,不能放在控制器里】,否则无法覆盖应用级响应生命周期。
配置 ContentNegotiator 行为以支持多格式回退
若项目需同时支持 JSON 和 XML(如对接遗留系统),必须启用内容协商机制,否则 Accept: application/xml 请求将直接 406 错误。
第一步:在 config/web.php 的 components.response.formatters 中追加 XML 格式器:
'xml' => [<br> 'class' => yiiwebXmlResponseFormatter::class,<br>],
第二步:在 API 控制器中启用 ContentNegotiator 行为:
public function behaviors()<br>{<br> $behaviors = parent::behaviors();<br> $behaviors['contentNegotiator'] = [<br> 'class' => yiiiltersContentNegotiator::class,<br> 'formats' => [<br> 'application/json' => yiiwebResponse::FORMAT_JSON,<br> 'application/xml' => yiiwebResponse::FORMAT_XML,<br> ],<br> ];<br> return $behaviors;<br>}
第三步:确保控制器继承 yii
estController,否则 ContentNegotiator 不会触发序列化流程,返回值将被忽略或报错。
统一错误响应为 JSON
Yii3 的 ErrorHandler 默认不强制 JSON 输出,未配置时 API 请求抛出异常仍可能返回 HTML 错误页,尤其当客户端未发送 Accept: application/json 时。
第一步:在 config/web.php 的 components 中配置 errorHandler:
'errorHandler' => [<br> 'errorAction' => 'api/error',<br>],
第二步:创建 controllers/ApiController.php,定义 actionError():
public function actionError()<br>{<br> $exception = Yii::$app->getErrorHandler()->exception;<br> if ($exception !== null) {<br> $response = [<br> 'code' => $exception->statusCode ?: 500,<br> 'message' => $exception->getMessage(),<br> 'data' => [],<br> ];<br> Yii::$app->response->statusCode = $exception->statusCode ?: 500;<br> return $response;<br> }<br>}
这一步必须手动设置 statusCode,否则即使返回数组,HTTP 状态码仍是 200,前端无法区分成功与失败。
验证响应头与输出内容
完成全部配置后,执行以下三步验证:
① 使用 curl 发送不带 Accept 头的请求:curl -X GET http://localhost/api/users,检查响应头是否含 Content-Type: application/json; charset=UTF-8;
② 在控制器中返回 return ['test' => '你好'];,确认响应体为 {"test":"你好"} 而非 {"test":"\u4f60\u597d"};
③ 故意触发异常(如访问不存在路由),确认返回 JSON 结构且状态码为 404 或 500,而非 HTML 页面源码。











