彻底解决php中文乱码需五个环节统一utf-8无bom:php文件编码、http响应头(header第一行)、html meta标签、数据库(utf8mb4)、外部文件/json转码,缺一不可。

PHP文件本身必须是UTF-8无BOM
这是起点。VS Code右下角显示“GBK”或“UTF-8 with BOM”,就直接失效——BOM会卡在php前面,导致header()报错,中文输出成问号或方块。
- 在VS Code中:点击右下角编码名 → “通过编码重新打开” → 选UTF-8 → 再点编码名 → “另存为编码” → 勾选“UTF-8(不带BOM)”并覆盖保存
- Notepad++用户:菜单栏“编码” → “转为UTF-8无BOM格式” → 保存
- Linux验证命令:
file -i your.php,输出应含charset=utf-8且**没有**“with bom”字样
HTTP响应头必须明确声明charset=utf-8
浏览器靠这个决定怎么解码字节流。没它,或写晚了,哪怕内容全是UTF-8,也会被当ISO-8859-1解析,结果就是乱码。
- 这行代码必须是PHP文件的**第一行有效内容**:
header('Content-Type: text/html; charset=utf-8'); - 前面不能有任何字符:空格、换行、tab、HTML、甚至?>关闭标签都不行
- 如果用了
require引入其他文件,那些文件也必须是UTF-8无BOM,且自身开头无空白 - 用
curl -I http://yoursite.com/test.php检查响应头是否真含该声明
HTML页面里不能少
它是后备机制。CDN可能缓存旧响应头,服务器全局配置可能覆盖PHP header,用户也可能手动改过浏览器编码——这时meta标签就是最后一道防线,必须和header严格一致。
-
<meta charset="UTF-8">要放在最开头,紧接标签 - 别写成
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">,HTML5只认charset简写 - 如果输出的是纯JSON接口,header应改为
Content-Type: application/json; charset=utf-8,meta可省略
数据库连接与字段必须用utf8mb4
MySQL的utf8是假UTF-8,最多支持3字节字符(不支持emoji和部分生僻汉字)。只改PHP页面,不改数据库层,查出来的还是乱码。
- 建库时执行:
CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 建表字段加:
VARCHAR(255) CHARACTER SET utf8mb4 - mysqli连接后立刻调用:
mysqli_set_charset($conn, 'utf8mb4'); - PDO连接DSN里必须写:
mysql:host=localhost;dbname=test;charset=utf8mb4 - 避免
SET NAMES utf8——它调的是MySQL那个残缺版utf8,不是utf8mb4
读取外部文件或处理JSON时要主动转码
file_get_contents()只读二进制,不做编码猜测;json_encode()只接受UTF-8输入,否则返回null或\uXXXX。
- 读GBK文本文件:
$content = mb_convert_encoding(file_get_contents('data.txt'), 'UTF-8', 'GBK'); - 输出JSON时启用选项:
json_encode($data, JSON_UNESCAPED_UNICODE) - 不确定源编码?先用
mb_detect_encoding($str, ['UTF-8','GBK','BIG5'], true)检测,再转 - 对中文字符串做长度、截取等操作,优先用
mb_strlen()mb_substr(),别用strlen()substr()
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











