
用 mb_strlen() 而不是 strlen()
PHP 默认的 strlen() 按字节计数,一个 UTF-8 中文字符占 3 字节,结果就是“你好”返回 6,完全不能反映真实字符数。mb_strlen() 才是专为多字节编码设计的函数,它能正确识别中文、日文、emoji 等 Unicode 字符。
必须显式指定编码,否则依赖默认内部编码(可能不是 UTF-8):mb_strlen($str, 'UTF-8')
- 不传第二个参数时,行为不可靠——尤其在
mb_internal_encoding()被改过或未设的情况下 - 如果字符串实际是 GBK 编码(比如老系统),却硬写
'UTF-8',结果会错乱甚至截断 - 常见错误现象:
mb_strlen("你好", 'UTF-8')返回 2 ✅;但mb_strlen("你好", 'GBK')返回 4 ❌(GBK 下每个中文占 2 字节,但它仍按字符逻辑算,所以其实也返回 2 ——重点是:别混用编码!)
注意 mb_strlen() 的扩展依赖和配置
这个函数属于 mbstring 扩展,不是 PHP 默认始终开启的。线上环境常有没装或被禁用的情况,直接调用会报 Fatal error: Uncaught Error: Call to undefined function mb_strlen()。
- 检查是否启用:
extension_loaded('mbstring')或运行php -m | grep mbstring - 没启用时,Apache 下需确认
php.ini中extension=mbstring未被注释;CLI 环境可能用的是另一份php.ini,得单独查 - 某些 Docker 镜像(如
php:alpine)默认不带mbstring,要手动apk add php82-mbstring类似操作
替代方案:没有 mbstring 时怎么安全 fallback
真遇到无法启用扩展的受限环境(比如某些共享主机),可用 iconv_strlen() 替代,它也支持多字节,且更轻量:
立即学习“PHP免费学习笔记(深入)”;
iconv_strlen($str, 'UTF-8')
- 它不依赖
mbstring,只要iconv扩展存在(PHP 几乎都自带) - 但要注意:当字符串含非法 UTF-8 序列时,
iconv_strlen()可能返回false,而mb_strlen()会尽力解析并返回近似值 - 别用正则
preg_match_all('/./u', $str)——性能差,且对某些组合字符(如带变音符号的汉字、ZWJ 连接 emoji)统计不准
中文长度计算的实际陷阱:全角/半角、空格、不可见字符
“中文字符长度”在业务中往往不只是技术问题。比如用户昵称限制 10 个字符,但“abc”(全角 ASCII)和“abc”(半角)视觉一样长,mb_strlen() 都算作 3;而“ ”(中文空格)、“ ”(全角空格)、零宽空格 \u200b 全都会被计入。
- 前端输入没过滤时,用户可能粘贴带格式文本,导致看似只有 5 个字,实际长度超限
- 建议入库前用
mb_ereg_replace('[[:space:]]+', ' ', $str)清理多余空白,或用trim()+mb_convert_kana()统一全半角(后者需mbstring) - emoji 表情如 ??、?? 在 UTF-8 下占多个码点,
mb_strlen()默认按 Unicode 码点计,通常没问题;但若需按“视觉字形”计数(比如排版),就得上 grapheme_* 函数了——那又是另一层复杂度
真正麻烦的从来不是“怎么算”,而是“算什么”——业务定义模糊时,mb_strlen() 给出的数字只是起点,不是答案。











