mb_convert_encoding 是 PHP 8.0+ 处理多语言数据时最易踩坑的函数,根源在于源编码误判而非语言支持问题;其候选编码列表须按实际概率降序排列(如 ['UTF-8','GBK','BIG5','Shift_JIS','EUC-JP']),避免双编码乱码,并需配合 mb_detect_encoding(true) 兜底及各环节独立编码验证。

mb_convert_encoding是 PHP 8.0+ 导入多语言数据时最常踩坑的函数,不是它不支持新语言,而是你传给它的源编码猜错了。
PHP 8.1+ 读 Excel 多语言内容必须用 getFormattedValue()
PhpSpreadsheet 2.x(PHP 8.0+ 唯一维护版本)默认 getValue() 会把带格式的中文/日文单元格转成数字或 DateTime 对象,直接丢掉原始字符串。真实场景中,班级通信录里的“張さん”“Nguyễn Văn A”全会变空或报错。
- 必须改用
$cell->getFormattedValue()—— 它强制返回字符串,保留原始字符 - 禁用自动类型推断:
$reader->setReadDataOnly(true),否则日期/数字字段仍可能被误解析 - 别碰
setEncoding():这个方法在 PhpSpreadsheet 中根本不存在,文档里写的是误导
mb_convert_encoding 的候选编码列表不能乱排
PHP 8.2 默认 mb_internal_encoding() 是 UTF-8,但 Excel 文件本身可能用 GBK(国产软件导出)、Shift_JIS(日文 Windows)、EUC-KR(韩文)——mb_convert_encoding($str, 'UTF-8', 'GBK, UTF-8') 这种写法极危险:如果字符串本来就是 UTF-8,先按 GBK 解再转 UTF-8,就双编码乱码了。
- 正确顺序是按实际出现概率降序:
mb_convert_encoding($str, 'UTF-8', ['UTF-8', 'GBK', 'BIG5', 'Shift_JIS', 'EUC-JP']) - 加兜底逻辑:若全部失败,用
mb_detect_encoding($str, ['UTF-8','GBK','BIG5'], true) ?: 'UTF-8'再试一次 - emoji 和组合字符(如 ??、العربية)容易触发
mb_convert_encoding的非法字符警告,此时必须配合@抑制或提前过滤
数据库存多语言字段前,mysqli_set_charset() 比 SET NAMES 更可靠
PHP 8.1+ 废弃了 mysql_connect(),但很多人还在用 mysqli 时漏掉字符集显式声明。即使表结构是 utf8mb4_unicode_ci,连接层没设对,中文进库仍是问号。
- 创建连接后立刻执行:
mysqli_set_charset($conn, 'utf8mb4') - 不要用
mysqli_query($conn, "SET NAMES utf8mb4"):它只影响当前查询,且在某些 MySQL 配置下不生效 - PDO 用户注意:
new PDO($dsn, $user, $pass, [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'])仍可用,但推荐直接在 DSN 加;charset=utf8mb4
真正卡住人的地方,从来不是“能不能读”,而是“读出来之后,下一环节(比如插入数据库、输出 JSON、生成 PDF)是否还保持原编码”。每个环节都要单独验证,不能假设上一步没乱码,下一步就安全。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











