Yii2 JSON中文乱码根源在于UTF-8编码链路断裂,需统一请求解析、数据库存储(utf8mb4)、响应头(charset=utf-8)三环节,并确保PHP文件、Web服务器、MySQL终端全为UTF-8。

Yii2表单验证中遇到JSON中文乱码,本质是编码链路断裂:前端传入UTF-8 JSON,但后端解析、数据库存储或响应输出任一环节未统一用UTF-8,就会出现“张三”变“å¼ ä¸”或空值。解决不靠猜,关键在三处堵点——请求体解析、数据存储、响应头声明。
确保请求体被正确识别为UTF-8 JSON
Yii2默认不自动解析application/json,必须显式启用JSON解析器,并确认它按UTF-8处理:
- 在
config/web.php的components['request']中配置:
'parsers' => ['application/json' => 'yii\web\JsonParser'] - 该解析器内部使用
json_decode($rawBody, true),前提是原始请求体本身是UTF-8编码——前端发送时必须保证JSON.stringify()输入的数据已是UTF-8(现代浏览器默认满足) - 若接口接收第三方系统(如微信、旧Java服务)发来的JSON,且其Content-Type含
charset=GBK,需在控制器里手动转码:
$raw = Yii::$app->request->getRawBody();<br>$rawUtf8 = mb_convert_encoding($raw, 'UTF-8', 'GBK');<br>$data = json_decode($rawUtf8, true);
数据库连接与字段必须用utf8mb4
即使JSON解析成功,存进数据库时若字符集不匹配,中文仍会变问号或截断:
- 数据库连接DSN中明确指定
charset=utf8mb4:
'dsn' => 'mysql:host=localhost;dbname=mydb;charset=utf8mb4' - 对应数据表及字段的字符集也设为
utf8mb4_unicode_ci(不是utf8,后者不支持emoji和部分生僻字) - 验证方式:执行
SHOW CREATE TABLE your_table,确认DEFAULT CHARSET=utf8mb4且字段COLLATE=utf8mb4_unicode_ci
验证失败提示返回JSON时声明UTF-8响应头
表单验证失败(如$model->validate() === false)后,若用Json::encode()返回错误信息,但没设Header,某些客户端(尤其老版WebView或微信内置浏览器)会按ISO-8859-1解析,导致中文乱码:
- 在返回JSON前强制设置响应头:
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;<br>Yii::$app->response->headers->set('Content-Type', 'application/json; charset=utf-8'); - 或更稳妥地直接输出:
header('Content-Type: application/json; charset=utf-8');<br>echo \yii\helpers\Json::encode(['error' => $model->getErrors()]);<br>Yii::$app->end(); - 避免使用
json_encode($data, JSON_UNESCAPED_UNICODE)——Yii2的Json::encode()默认已等效此行为,无需额外加参数
额外检查点:文件与环境编码
容易被忽略但高频出问题的地方:
-
config/main.php等PHP配置文件本身必须保存为UTF-8无BOM格式(用Notepad++或VS Code检查并转码) - Web服务器(Nginx/Apache)未强制输出UTF-8时,在Nginx配置中加:
charset utf-8;(放在http/server/location块中) - 若用MySQL命令行导入初始SQL,确保终端编码为UTF-8,或SQL文件开头加
SET NAMES utf8mb4;


















