必须用 mb_strlen($str, 'UTF-8') 判断 Unicode 字符串长度,禁用 strlen();需确保 mbstring 启用,对不确定编码先转 UTF-8,零宽字符须正则清洗后再计算,大文本应分层处理,截取必用 mb_substr()。

PHP 7.2 判断含 Unicode 字符(如中文、希伯来文、亚美尼亚文、emoji、零宽字符等)的字符串长度,核心原则只有一条:绝不能用 strlen()。它按字节计数,而 UTF-8 下一个 Unicode 字符可能占 1–4 字节,结果完全失真。
必须用 mb_strlen() 并显式指定编码
mb_strlen() 是 PHP 7.2 中处理 Unicode 字符串长度的标准函数,但有关键细节:
- 务必传入第二个参数:
mb_strlen($str, 'UTF-8')—— 不写或依赖mb_internal_encoding()极易出错,尤其在 CLI 或多环境部署时 - 确认
mbstring扩展已启用:运行php -m | grep mbstring,未启用会报Call to undefined function mb_strlen() - 若输入来源不确定编码(如旧系统接口、文件上传),先做归一化:
$safe = mb_convert_encoding($input, 'UTF-8', 'auto')
警惕零宽字符干扰语义长度
像 U+200B(零宽空格)、U+FEFF(BOM)、U+200C/U+200D 等控制符,在视觉和业务上“不占长度”,但 mb_strlen() 仍计为 1。需清洗后判断:
- 用正则清除主流零宽字符:
preg_replace('/[\x{200b}-\x{200f}\x{202a}-\x{202e}\x{feff}]/u', '', $str) -
/u修饰符不可省,否则 UTF-8 多字节序列会被误解析 - 清洗后再调用
mb_strlen($cleaned, 'UTF-8'),才接近真实“有效字符数”
大文本或性能敏感场景要分层处理
对几 MB 以上的字符串,直接 mb_strlen() 可能慢且吃内存。可按需分级:
立即学习“PHP免费学习笔记(深入)”;
- 仅需快速拦截超限?用
fstat()查文件体积,按平均字节数估算字符量(如中英混排用系数 2.5) - 需精确字符数但内存受限?先用
strlen()快速排除(例:限制 1000 字符,字节长已超 4000,则大概率超标) - 真正要截取显示内容?必须用
mb_substr($str, 0, 50, 'UTF-8'),substr()会切乱码
别用正则“测长度”,那是弯路
像 preg_match('/^.{10}$/u', $str) 看似可行,但隐患多:
- 无法处理换行符(
.默认不匹配\n) - 对 ZWJ 序列(如 ??)、代理对 emoji 等,码点数 ≠ 显示宽度,
mb_strlen()和正则都返回 4,但人眼只看到 1 个图标 - 性能差、易写错、类型不安全——
mb_strlen()更直白可靠



















