必须显式声明charset,因Yii默认不设MySQL连接字符集,即使库表为utf8mb4,PHP驱动仍可能以latin1连接导致中文乱码;dsn须含charset=utf8mb4,且文件编码、响应头、中间件均需统一UTF-8。
数据库连接配置必须显式声明 charset
Yii 默认不会自动设置 MySQL 连接的字符集,哪怕数据库、表、字段全是 utf8mb4,PHP 驱动仍可能以 latin1 建立连接,导致 SELECT 出来的中文变成问号或乱码。
在 config/db.php 或数据库配置数组中,dsn 字符串末尾必须加上 charset=utf8mb4(推荐)或 charset=utf8:
'dsn' => 'mysql:host=localhost;dbname=myapp;charset=utf8mb4',
-
utf8mb4支持完整 Unicode(含 emoji、生僻汉字),utf8在 MySQL 中实际是utf8mb3,有兼容性隐患 - 不要只改数据库或表的字符集,不配 DSN 的
charset无效 - 如果用的是 MySQL 5.7+,建议同时在
my.cnf中确认collation-server = utf8mb4_unicode_ci和init-connect='SET NAMES utf8mb4'
REST 接口响应头需强制指定 Content-Type 编码
Yii2 REST 模块默认使用 yii\web\Response,但若没显式设置 charset,浏览器或客户端可能按 ISO-8859-1 解析 JSON,导致中文显示为 \u4f60\u597d 或直接乱码。
在 config/web.php 的 components 中补全 response 配置:
Flux AI
Flux AI,释放你的想象力,用文字生成图像
下载
'response' => [
'class' => 'yii\web\Response',
'format' => yii\web\Response::FORMAT_JSON,
'charset' => 'UTF-8',
'acceptMimeType' => 'application/json',
],
- 缺了
'charset' => 'UTF-8'这一行,Content-Type响应头会是application/json; charset=ISO-8859-1 - 不要依赖前端 JS 自动解码 ——
fetch或axios都会严格按响应头的charset解析 - 如果用了自定义
on beforeSend回调,确保没覆盖或清空$response->charset
文件保存与编辑器编码必须为 UTF-8(无 BOM)
控制器、模型、视图 PHP 文件本身若以 ANSI/GBK 编码保存,即使数据库和响应头都对,PHP 解析时就会把源码里的中文字符串字面量读错,输出必然乱码。
- 用 VS Code / PHPStorm 打开文件,右下角确认编码显示为
UTF-8,不是UTF-8 with BOM或GBK - Sublime Text:菜单 → File → Save with Encoding → UTF-8
- 别信编辑器“自动识别”,手动设一次并勾选“默认为此编码”
- 检查
index.php入口文件顶部有没有隐藏的 BOM 字节(可用 hex editor 查看前 3 字节是否为EF BB BF)
避免中间层隐式转码(如 Nginx / Apache 代理)
当 Yii 应用部署在 Nginx 后面,且 Nginx 配置了 charset GBK 或未声明 charset,它可能重写响应头,覆盖 Yii 设置的 UTF-8。
- Nginx 配置里禁用全局
charset指令,或明确写成charset utf-8; - Apache 的
AddDefaultCharset若设为Off或UTF-8,否则会插手响应头 - 用
curl -I http://your-api/user实际抓包,确认返回的Content-Type是application/json; charset=UTF-8,而不是被中间件篡改过
乱码问题从来不是单点故障,而是字符集在「文件→PHP解析→数据库连接→HTTP响应→客户端解析」整条链路上任一环节断裂所致。最容易忽略的是 DSN 里漏掉 charset= 和编辑器保存编码这两个实操细节。