mb_convert_encoding 是最可靠的选择,但必须显式传入源编码;漏掉第三个参数会导致乱码或空字符串,正确写法为 mb_convert_encoding($str, 'utf-8', 'gbk')。

mb_convert_encoding 是当前最可靠的选择,但必须显式传入源编码;漏掉第三个参数或依赖自动检测,90% 的乱码问题就出在这一步。
mb_convert_encoding 必须传第三个参数
很多人写 mb_convert_encoding($str, 'UTF-8') 就以为完事了,结果中文还是乱码,甚至返回空字符串。这不是函数坏了,是它根本没猜对源编码——默认按 mb_internal_encoding() 的值(通常是 UTF-8)去解析,而你的原始字符串其实是 GBK 字节流,直接被当成非法 UTF-8 截断或静默失败。
正确做法永远带齐三个参数:
-
mb_convert_encoding($str, 'UTF-8', 'GBK')—— 明确告诉 PHP:“这串字节当前是 GBK 编码” - 源编码不区分大小写,但推荐用标准大写名:
GBK、GB18030、UTF-8、BIG5 - 别信
'auto':它本质是按顺序试['UTF-8', 'ISO-8859-1']等,短文本、纯英文、带 BOM 的 UTF-8 都容易误判
iconv 用不好会丢数据或报错中断
iconv 比 mb_convert_encoding 更底层、更快,但也更“较真”。默认遇到无法转换的字节(比如 GBK 里某个字在 UTF-8 中无对应),直接抛出 iconv(): Illegal character 并中止执行。
加后缀能绕过,但行为差异极大:
-
iconv('GBK', 'UTF-8//IGNORE', $str)—— 直接删掉所有无法转换的字节,可能导致句子缺字、URL 损坏 -
iconv('GBK', 'UTF-8//TRANSLIT', $str)—— 对中文基本无效(「℃」→「C」这种替换不适用),还可能引入不可预知字符 - PHP 8.2+ 已废弃
iconv扩展(仍可用),新项目请优先用mb_convert_encoding
转换前先验证源编码,别只靠 guess
如果真不确定源编码,可以用 mb_detect_encoding($str, ['UTF-8', 'GB18030', 'GBK', 'BIG5'], true) 辅助判断,但注意:
- 第三个参数必须为
true,否则它会跳过 ASCII 字节,导致纯英文文本全判成 UTF-8 该函数返回的是“第一个匹配项”,不是“最可能项”,短文本(如 - 更靠谱的方式是结合上下文:HTTP 请求头里的
Content-Type: text/plain; charset=gbk、数据库字段定义的CHARACTER SET gbk、文件开头是否有 BOM(hexdump -C file.txt | head查看前 3 字节) - 转换后务必用
mb_check_encoding($str, 'UTF-8')验证,避免“看似成功,实则失败”
"测试")极易误判
数据库乱码不是 PHP 字符串的问题
从 MySQL 读出来的中文是乱码,光在 PHP 里调 mb_convert_encoding 没用。数据在进 PHP 前就已经损坏了。
必须三处同步设对编码:
- 连接层:
PDODSN 加;charset=utf8mb4;mysqli连接后立刻调$mysqli->set_charset('utf8mb4') - 表结构:
SHOW CREATE TABLE xxx确认字段带CHARACTER SET utf8mb4(不是utf8) - PHP 输出:
header('Content-Type: text/html; charset=utf8')+ HTML 中<meta charset="utf-8">
最容易被忽略的是:SET NAMES utf8 ≠ SET NAMES utf8mb4,前者不支持 emoji 和部分生僻汉字,后者才是真正的 UTF-8 实现。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











