strlen() 计算字节数而非字符数,对UTF-8中文/emoji等返回字节数(如5汉字→15);需字符数时必须用mb_strlen($str, 'UTF-8'),否则国际化场景易出错。

PHP 的 strlen() 不区分大小写,只数字节
strlen() 完全不关心字符是大写还是小写,它只是按字节(byte)逐个计数。对 ASCII 字符(如 a 和 A),它们各占 1 字节,所以长度相同;但对中文、emoji 或带重音的字母(如 é),在 UTF-8 编码下可能占 2–4 字节,strlen() 仍照数不误——这常导致“看起来是 5 个汉字,结果返回 15”。
要按“字符数”而非“字节数”,得用 mb_strlen()
真正按“人眼看到的字符个数”计算,必须指定编码并使用多字节函数:
-
mb_strlen($str, 'UTF-8')是安全默认,尤其处理中文、日文或用户输入时 - 漏写第二个参数(如
mb_strlen($str))会依赖mb_internal_encoding()当前值,线上环境容易不一致 -
mb_strlen()和strlen()对纯 ASCII 字符串结果相同,但逻辑完全不同——前者是字符计数,后者是字节计数
大小写转换本身不影响长度,但可能改变字节分布
像 strtoupper() 或 mb_strtoupper() 这类函数,对英文字符不会增减字节,但对某些语言字符可能有影响:
- 土耳其语中
i→İ(带点大写),UTF-8 下从 1 字节变成 2 字节 - 德语
ß转大写为SS,字符数 +1,字节数也 +1 - 所以
strlen(strtoupper($str))可能 ≠strlen($str),虽然极少发生,但国际化项目里不能假设相等
判断长度前,先确认你到底需要什么“长”
界面显示限制(如“最多 10 个汉字”)、数据库字段截断、API 参数校验——这些场景几乎都该用字符数,而不是字节数:
立即学习“PHP免费学习笔记(深入)”;
- 表单验证:用
mb_strlen($input, 'UTF-8') ,别用strlen() - MySQL
VARCHAR(255)存 UTF-8 字符时,实际能存的汉字远少于 255 个(因每个汉字 3 字节),但业务逻辑里的“长度限制”仍应按字符理解 - 如果真要按字节截断(比如协议头固定长度),才用
strlen()配合substr(),但务必加注释说明“此处按字节操作”
最容易被忽略的是:开发时本地环境用的可能是默认 Latin-1,而生产是 UTF-8,mb_strlen() 不带编码参数就跑,结果在测试机上对、上线就错。











