必须用 mb_strlen 判断中文字符串长度,因 strlen 按字节计数导致 UTF-8 中文长度错误;mb_strlen 需显式指定 'UTF-8' 编码,且依赖 mbstring 扩展;纯 ASCII 场景可用更快的 strlen;含 emoji 等组合字符时应改用 grapheme_strlen。

判断中文字符串长度必须用 mb_strlen
PHP 的 strlen 按字节计数,对 UTF-8 编码的中文会返回错误长度(比如一个汉字算 3 字节),直接导致截断、验证失败或分页错乱。只要字符串可能含中文、日文、emoji 或其他多字节字符,mb_strlen 是唯一安全选择。
常见错误现象:strlen("你好") 返回 6,而实际字符数是 2;用它做表单长度限制时,用户输两个汉字就“超限”了。
-
mb_strlen默认使用内部编码(由mb_internal_encoding()决定),建议显式指定:mb_strlen($str, 'UTF-8') - 若未启用
mbstring扩展,调用mb_strlen会报Fatal error: Uncaught Error: Call to undefined function mb_strlen() - 在 CLI 环境中,
mb_internal_encoding()可能默认为ISO-8859-1,不指定编码参数极易出错
strlen 仅适用于纯 ASCII 场景
当你 100% 确保字符串只含英文、数字、标点(即每个字符占 1 字节),strlen 更快、无扩展依赖。典型场景:UUID、base64 编码串、HTTP 头字段值、数据库主键哈希。
性能差异明显:strlen 是 C 层直接读内存长度,mb_strlen 需逐段解析多字节序列,大数据量下可差出 2–5 倍耗时。
立即学习“PHP免费学习笔记(深入)”;
- 不要因为“怕出错”就全局替换为
mb_strlen——没必要的开销和扩展耦合 - 用
ctype_print($str) && !preg_match('/[\x80-\xFF]/', $str)可粗略检测是否为纯 ASCII,但生产环境更推荐靠输入契约保证 - JSON 字符串本身是 UTF-8,但若你确定内容全为 ASCII(如
{"id":123,"name":"abc"}),仍可用strlen做快速长度预判
替代方案:grapheme_strlen 处理组合字符
当字符串含 emoji(如 ??)、带重音符号的字母(如 é, ñ)或 ZWJ 序列时,mb_strlen 仍可能高估“视觉字符数”。例如 "??" 是 7 个 UTF-8 字节、4 个 Unicode 码点,但用户认为它是 1 个字符——这时要用 grapheme_strlen。
- 需要启用
intl扩展,且 PHP ≥ 7.2 - 性能比
mb_strlen更低,仅在富文本、用户名显示、前端对齐等强用户体验场景中考虑 - 别把它当作
mb_strlen的“升级版”:大多数后端逻辑(如数据库字段校验、API 参数限制)只需字符数(mb_strlen),不需要图形单元数
上线前必须检查的三件事
很多线上 bug 来自本地开发环境和生产环境的编码配置不一致,而不是函数选错。
- 确认
mbstring.func_overload未开启(该配置会静默覆盖strlen等函数行为,已废弃且极度危险) - 检查
phpinfo()中mbstring.internal_encoding是否为UTF-8;若不是,不要依赖默认值,始终显式传参 - 用
bin/hexdump -C或unpack('H*', $str)实际查看字符串二进制内容,比猜编码更可靠
字符长度从来不是孤立函数问题,而是编码设定、扩展可用性、业务语义三层叠加的结果。漏掉任意一层,mb_strlen 也救不了。











