ThinkPHP接口中文乱码主因是编码链路不一致:数据库字段GBK未转码、header缺失、mb_convert_encoding时机错误或php://input被提前消费。须在echo前设Content-Type charset,DB字段应改为utf8mb4,响应前统一转UTF-8。

ThinkPHP 接口返回中文乱码,基本不是框架“没转好”,而是原始响应体编码(如 GBK)和 PHP 解析/输出流程不匹配——mb_convert_encoding 用错时机、header 漏设、或 php://input 被提前消费,都会导致乱码不可逆。
接口返回 GBK 字符串时,直接 echo 就乱码
TP6 的 json()、success() 等响应方法默认按 UTF-8 输出,但如果控制器里手动 echo mb_convert_encoding($gbkStr, 'UTF-8', 'GBK'),却忘了设 header,浏览器仍会按 ISO-8859-1 或 GBK 解析字节流。
- 必须在
echo前加:header('Content-Type: application/json; charset=utf-8')(JSON 接口)或header('Content-Type: text/plain; charset=utf-8')(纯文本) - 不要依赖浏览器自动探测:Chrome/Firefox 对无
charset的Content-Type: application/json默认当 UTF-8,但 IE、某些嵌入式 HTTP 客户端会 fallback 到系统 locale(如 GBK) - 若返回的是 HTML 片段(比如富文本编辑器内容),也要确保
header('Content-Type: text/html; charset=utf-8'),否则<meta charset="utf-8">在响应体里也无效
file_get_contents 或 curl 调用外部接口后中文乱码
这不是 TP 的问题,而是你调用方没处理响应原始编码。很多老政务/银行接口返回 GBK 字节但 Content-Type 不带 charset=gbk,PHP 就当 UTF-8 解析,结果是乱码。
- 先确认真实编码:用
bin2hex(substr($content, 0, 4))看前几个字节,比如'c4e3'是 GBK 的「你」,'e4bda0'才是 UTF-8 - 解码要放在
json_decode()或simplexml_load_string()之前:$content = mb_convert_encoding($content, 'UTF-8', 'GBK') - 别用
mb_detect_encoding($content, ['UTF-8','GBK'], true)做判断——它对短文本、纯数字+中文混合的字符串极易误判;优先靠业务约定或自定义 header(如X-Response-Charset: GBK) - 如果目标接口只认
Accept-Charset: gbk,那 curl 请求时就得加:curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept-Charset: gbk'])
TP6 的 response()->json() 返回空或问号
常见于数据库查出 GBK 编码字段(比如从旧系统迁移的表),而 TP6 默认把所有查询结果当 UTF-8 处理。一旦字段实际是 GBK 字节,json_encode() 会因非法 UTF-8 序列返回 false 或静默替换为 。
立即学习“PHP免费学习笔记(深入)”;
- 检查字段真实编码:用
bin2hex(substr($row['name'], 0, 2))看是否是c4e3类 GBK 双字节 - 不能在模型
getAttr里用mb_convert_encoding—— 因为json()序列化时已触发,此时转码无效;必须在赋值给数组前转:$data['name'] = mb_convert_encoding($row['name'], 'UTF-8', 'GBK') - 更彻底的解法:改表结构,把字段
CHARACTER SET改成utf8mb4,并执行ALTER TABLE t MODIFY name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 临时兜底:在全局异常处理里捕获
json_encode()失败,用mb_convert_encoding($data, 'UTF-8', 'auto')(注意auto不含 GBK,得手动指定)
自定义错误页和 dump() 输出乱码
TP6 的 halt() 和 dump() 函数默认不发 Content-Type header,开发时用 Chrome 查看就乱码,尤其 Windows 下 PHP 文件本身带 BOM 更明显。
- 修改
think\helper\php\function.php中的halt(),在include模板前加:header('Content-Type: text/html; charset=utf-8') - 同理,在
dump()函数开头加同样 header;或者更简单:在入口文件public/index.php最顶部加header('Content-Type: text/html; charset=utf-8')(适用于调试环境) - 如果
dump()输出到 CLI(命令行),乱码是终端编码问题,跟 PHP 无关;Windows CMD 需执行chcp 65001,Linux/macOS 确保LANG=en_US.UTF-8 - BOM 是隐形杀手:用 VS Code 打开函数文件,右下角看编码是否为
UTF-8且无 BOM;有 BOM 就点「Save with Encoding → UTF-8」重新保存
真正难处理的不是单点转码,而是整个链路里任意一环(请求头、输入流、DB 字段、PHP 内部编码、响应头、浏览器解析)用了不同字符集——只要漏掉一个 header 或错配一次 mb_convert_encoding 参数顺序,乱码就不可逆。建议从数据库字段编码开始倒查,而不是在 response 层反复 patch。



















