strlen()按字节计数,西里尔字母UTF-8编码占2字节,故返回值非字符数;应使用mb_strlen($str, 'UTF-8')并确保字符串为UTF-8编码。

PHP 默认的 strlen() 会把一个西里尔字母(如 а、ж)算作 2 或 3 个字节,而不是 1 个字符 —— 所以它不能正确返回“字符数”。
为什么 strlen() 在西里尔字母上失效
因为 PHP 的 strlen() 是字节计数器,不是字符计数器。西里尔字母在 UTF-8 编码下占 2 字节(如 а U+0430 → \xd0\xb0),而 strlen("а") 返回 2,不是你想要的“1 个字符”。
- UTF-8 中西里尔基本字母范围:U+0400–U+04FF,全部是 2 字节编码
-
mb_strlen($str, 'UTF-8')才按 Unicode 字符计数,返回1 - 若未指定编码(如
mb_strlen($str)),依赖mb_internal_encoding(),易出错
必须用 mb_strlen() 并显式指定 'UTF-8'
这是最稳妥的做法,不依赖运行时默认编码,也不受 mb_internal_encoding() 变更影响。
- 永远显式传入
'UTF-8'第二参数,避免隐式依赖 - 确保源文件本身是 UTF-8 编码(无 BOM),否则字符串字面量可能乱码
- 如果从数据库或 HTTP 请求读取,确认输入已转为 UTF-8(如用
mb_convert_encoding())
判断是否含西里尔字母:用 preg_match() 配合 Unicode 属性
单纯测长度不够,有时你需要知道字符串“是否含西里尔字符”,比如做输入校验。
立即学习“PHP免费学习笔记(深入)”;
-
/u修饰符启用 UTF-8 模式,否则\p{Cyrillic}不生效 -
\p{Cyrillic}匹配所有西里尔区块字符(含扩展如西里尔补充、西里尔增强等) - 不要用
/[а-яА-ЯёЁ]/这类范围写法 —— 它漏掉很多合法西里尔字符(如і、ї、є等乌克兰字母)
真正容易被忽略的是:字符串来源是否可信 UTF-8。哪怕你用了 mb_strlen($str, 'UTF-8'),如果 $str 实际是 Windows-1251 编码的二进制数据,结果仍是错的 —— 测长前先确认并转换编码,比选函数更重要。











