根本原因是substr等单字节函数按字节截取UTF-8中文(占3字节),导致字符被截断;应统一使用mb_substr($str,$start,$length,'UTF-8')等多字节函数,并确保mbstring扩展启用、编码显式指定或设为UTF-8。

PHP 7.4 截取中英文混合字符串出现乱码,根本原因是用了单字节函数(如 substr)处理 UTF-8 多字节字符——中文在 UTF-8 中占 3 字节,被硬切会截断字节流,导致后续显示为 或乱码。
必须用 mb_ 系列多字节函数
PHP 默认不识别 UTF-8 字符边界,substr、strlen、strpos 等都按字节操作。解决办法是统一改用 mb_ 开头的函数,并确保内部编码设为 UTF-8:
- 用
mb_substr($str, $start, $length, 'UTF-8')替代substr - 用
mb_strlen($str, 'UTF-8')替代strlen计算真实字符数 - 脚本开头加
mb_internal_encoding('UTF-8');,避免每次调用都传编码参数 - 确认 php.ini 中已启用
extension=mbstring,且未被注释
检查并清理输入源的编码
即使函数用对了,若原始字符串本身不是合法 UTF-8,截取后仍可能出错:
- 用
mb_detect_encoding($str, ['UTF-8', 'GBK', 'BIG5'], true)检查实际编码 - 若非 UTF-8,先转码:
$safe = mb_convert_encoding($str, 'UTF-8', 'GBK'); - 对不可信输入(如表单、文件读取),可用
mb_scrub($str)(PHP 7.2+)或iconv('UTF-8', 'UTF-8//IGNORE', $str)清洗非法字节
注意 BOM 和隐藏字符干扰
文件开头的 UTF-8 BOM(\xEF\xBB\xBF)或不可见控制字符,会导致 mb_strlen 计数偏大、截取位置偏移:
- 用 VS Code / Notepad++ 打开 PHP 文件,右下角确认编码为 “UTF-8 without BOM”
- 读取外部文本时,先用
ltrim($content, "\xEF\xBB\xBF")去 BOM - 避免在
前留空行、空格或注释——这些都会被当作输出,影响 header 发送
输出前确保环境一致
截取正确但浏览器显示仍乱码?说明输出环节断链:
- 页面顶部(任何输出前)加
header('Content-Type: text/html; charset=utf-8'); - HTML 的
中加,且放在前 - 数据库查询结果若参与截取,需确认连接已设为 utf8mb4:
$pdo->exec("SET NAMES utf8mb4");或 DSN 中含;charset=utf8mb4
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











