thinkphp中文乱码需全链路修复:确保php文件为utf-8无bom;数据库全程启用utf8mb4(服务端、dsn、表结构、set names);模板用msubstr替代substr;json返回启用json_unescaped_unicode;导出前调用ob_end_clean()并按格式加bom。

ThinkPHP 中文乱码不是单一问题,而是编码链路断裂的综合表现。真正有效的修复,必须覆盖「文件编码→HTTP响应→数据库连接→模板渲染→JSON/导出/二维码等特殊输出」全环节,漏掉任一环都可能前功尽弃。
确保所有 PHP 文件是 UTF-8 无 BOM
这是最基础也最容易被忽略的一环。哪怕一个配置文件、路由文件或中间件开头带了 BOM(EF BB BF),就会导致 header() 失效、JSON 格式损坏、接口返回空或报 Unexpected token in JSON。
- 用 VS Code 或 Notepad++ 打开
app/、config/、route/、common.php等所有 PHP 文件,统一另存为「UTF-8 without BOM」 - 禁用任何调试性
echo、var_dump,避免 Notice 级错误(如访问未定义数组键)产生隐式输出 - 检查第三方扩展或 Composer 包引入的文件,尤其注意老旧插件自带的 PHP 文件是否含 BOM
数据库读写全程启用 utf8mb4
仅把表字符集设为 utf8mb4_unicode_ci 不够——MySQL 服务端、PDO 连接、建表语句三者必须全部对齐,否则中文、emoji 会变 ??? 或截断。
- MySQL 配置文件(
my.cnf或my.ini)中设置:character-set-server = utf8mb4,重启 mysqld - ThinkPHP 的
database.php中,删掉'charset' => 'utf8mb4'这类配置(它在 DSN 存在时无效),直接在'dsn'里硬写:'dsn' => 'mysql:host=127.0.0.1;dbname=test;charset=utf8mb4' - 已有表执行:
ALTER TABLE `table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 在
app/common.php中手动补一句:Db::connect()->execute('SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci');
模板中截中文不乱码:用 msubstr 替代 substr
模板里写 {:substr($str,0,10)} 必乱码——因为 PHP 原生 substr() 按字节切,UTF-8 中文占 3 字节,极易从中切断。
- 不要修改框架源码或硬写正则;在
app/common.php中定义安全函数:function msubstr($str, $start = 0, $length = null, $encoding = 'utf-8') { return mb_substr($str, $start, $length, $encoding); } - 确认服务器已启用
mbstring扩展:php -m | grep mbstring,若无输出,需在php.ini中取消;extension=mbstring前的分号并重启 PHP - 模板中调用:
{:msubstr($title, 0, 15)},无需再传编码参数(函数内已固定)
接口 JSON 中文不转义、不损坏
中文显示为 \u4f60\u597d 是默认行为,不算 bug;但若出现问号、方块、解析失败,说明源头或响应流程出了问题。
- TP6.1+:在
config/app.php中配置:'json_encode' => [JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES] - TP6.0 或需兼容旧版:控制器中统一用
return json($data, 200, [], JSON_UNESCAPED_UNICODE);,严禁json(json_encode(...))双重编码 - Postman/curl 测试时,必须带请求头:
Accept: application/json和Content-Type: application/json - 若前端仍乱码,检查数据源本身:数据库查出字段是否已是乱码?POST 提交是否用了 GBK 编码?可在控制器开头加
var_dump($_POST)验证原始输入
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











