应使用 mb_strlen($str, 'UTF-8') 获取字符串真实字符数,它按 Unicode 字符而非字节计数;需确保字符串为 UTF-8 编码,必要时用 mb_convert_encoding 转换;对复杂 emoji 组合,grapheme_strlen 更精确。

PHP 8.2 中要准确获取字符串的字符数(特别是含中文、emoji、Unicode 字符时),不能用 strlen(),因为它返回的是字节数。必须使用多字节字符串函数。
用 mb_strlen() 获取真实字符数
mb_strlen() 是 PHP 处理 Unicode 字符串的标准方式,它按字符(code point)计数,不是字节。需确保启用了 mbstring 扩展(PHP 8.2 默认启用)。
- 基本用法:
mb_strlen($str, 'UTF-8')—— 显式指定编码更安全 - 若省略第二参数,会使用
mb_internal_encoding()的当前值,建议不依赖默认值 - 例如:
mb_strlen("你好?", 'UTF-8')返回 4(2个汉字 + 1个 emoji = 3个 Unicode 字符?等等——实际是“你好”2字符 + “?”1个 emoji,共3;但注意:某些 emoji 是组合序列,如 ?? 实为多个 code point,mb_strlen按 UTF-8 code unit 计算,对标准 emoji 通常正确,对 ZWJ 组合需额外处理)
确认字符串编码是 UTF-8
如果源字符串不是 UTF-8(比如 GBK 或 ISO-8859-1),mb_strlen 可能误判。可用 mb_detect_encoding() 粗略检测,但更可靠的是在输入源头统一转为 UTF-8:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
$str = mb_convert_encoding($str, 'UTF-8', 'auto');- 或明确指定来源编码:
mb_convert_encoding($str, 'UTF-8', 'GBK'); - Web 表单提交、数据库读取等环节也应保持 UTF-8 一致
区分“字符数”和“视觉字形数”(可选进阶)
严格来说,mb_strlen 统计的是 Unicode code units(UTF-8 下每个字符对应 1~4 字节,但函数内部按字符逻辑计数)。对于大多数场景(含中文、常见 emoji),它就是你想要的“人眼看到的字数”。但以下情况需注意:
立即学习“PHP免费学习笔记(深入)”;
- 变体选择符(如 ?? 后跟 VS16)、组合字符(如 é 带重音)会被视为独立字符计数
- 零宽连接符(ZWJ)序列如 ?? 在
mb_strlen中通常计为 1(PHP 8.2 的 mbstring 对常见 ZWJ 序列有基础支持),但并非所有组合都完全准确 - 如需精确图形单元(grapheme cluster)计数(即真正“一个字形”),可用
grapheme_strlen($str),它基于 ICU 库,更贴近显示效果,但需确保 intl 扩展已启用
避免踩坑:不要用 strlen 或 count_chars
strlen() 对 "你好" 返回 6(UTF-8 下每个汉字占 3 字节),count_chars() 统计字节频次,完全不适用。也不要用 str_split() 后 count,它同样按字节切分,中文会乱码断裂。
- 错误示例:
strlen("abc你好")→ 9(不是 5) - 正确替代:
mb_strlen("abc你好", 'UTF-8')→ 5


















