应使用 mb_strlen($str, 'utf-8') 获取字符串语义长度,因其按 unicode 码点计数,统一将半角、全角、中文、emoji 等均视为 1 字符;strlen() 仅统计字节数,遇多字节字符(如中文、emoji、零宽符)会严重失真。

PHP 8.0 判断含半角字符的字符串长度,关键不是“区分半角”,而是统一按 Unicode 字符(码点)计数——因为半角英文字母、数字、标点(如 a、1、.)在 UTF-8 中占 1 字节,但和全角字符(如 a、1)一样,都算作 1 个逻辑字符。用户感知的“长度”,就是这种字符个数,不是字节数。
所以正确做法是:用 mb_strlen($str, 'UTF-8'),而不是 strlen()。
✅ 为什么不能用 strlen()?
-
strlen()统计的是字节数。 - 半角 ASCII 字符(如
Hello)每个占 1 字节 →strlen("Hello")返回5,碰巧对; - 但只要混入中文、emoji 或零宽字符,结果就错:
-
"Hi你好"→strlen()返回7(H+i各1字节,你好各3字节),而用户认为是 4 个字符; -
"ab"(中间含 U+200B 零宽空格)→strlen()返回4,但mb_strlen()返回3,且业务上应视作 2 个可见字符。
-
✅ PHP 8.0 推荐写法(含清洗与校验)
// 1. 归一化编码(防损坏 UTF-8)
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
// 2. 清除常见零宽控制符(避免“看不见却占长度”)
$str = preg_replace('/[\x{200b}\x{200c}\x{200d}\x{2060}\x{feff}]/u', '', $str);
// 3. 去首尾空白(trim 对零宽无效,所以这步在清洗之后)
$str = trim($str);
// 4. 获取语义长度(含半角、全角、中文、emoji,全部统一为 1 个字符)
$length = mb_strlen($str, 'UTF-8');
⚠️ 注意:
mb_strlen()必须显式传'UTF-8',不能省略。PHP 8.0 虽默认mbstring.internal_encoding为 UTF-8,但函数调用不依赖该设置,显式指定更可靠。
✅ 半角 vs 全角?业务上要不要区分?
一般不需要主动区分:
- 表单昵称、评论、搜索关键词等场景,用户输入
ABC和ABC都算 3 个字符; - 若需强制限制“只允许半角”,那是字符集校验问题,不是长度问题,应配合正则:
// 只允许 ASCII 半角字符(不含空格、控制符) if (!preg_match('/^[ -~]*$/', $str)) { throw new InvalidArgumentException('仅支持 ASCII 半角字符'); }
✅ 小技巧:快速判断是否“纯半角可打印字符”
// 检查是否全为 ASCII 可见字符(空格到波浪号,即 0x20–0x7E)
function isAsciiPrintable($s) {
return is_string($s) && $s === '' || preg_match('/^[ -~]*$/', $s);
}
满足该条件时,mb_strlen($s, 'UTF-8') === strlen($s) 恒成立,此时二者可互换(但不建议因此改用 strlen(),逻辑一致性更重要)。
不复杂但容易忽略
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











