strlen() 返回字节数而非字符数,utf-8下汉字占3字节;需用mb_strlen($str, 'utf-8')获取正确字符数,并确保mbstring扩展已启用且输入统一为utf-8。

strlen() 返回的不是“不对”,而是它本来就不统计汉字个数——它只数字节。UTF-8 下一个汉字占 3 字节,strlen("你好") 返回 6 是完全正确的,只是你想要的是字符数,不是字节数。
必须用 mb_strlen() 替代 strlen()
PHP 7.2 已内置 mbstring 扩展(但可能未启用),mb_strlen() 是唯一能按字符计数的标准函数:
- 调用时务必传入编码:
mb_strlen($str, 'UTF-8'),不能省略第二个参数 - 若不传编码,会 fallback 到
mb_internal_encoding()的当前值,而该值在 PHP 7.2 中默认是ISO-8859-1,会导致中文全算成 1 字符/字节,结果仍错 - 验证是否可用:
function_exists('mb_strlen'),返回false就说明扩展没开
检查并启用 mbstring 扩展(PHP 7.2 常见坑)
PHP 7.2 默认不自动加载 mbstring,尤其在 Docker、轻量镜像或自编译环境中:
- Linux(apt):
sudo apt install php7.2-mbstring && sudo systemctl restart php7.2-fpm - macOS(Homebrew):
brew install php@7.2通常已含,但需确认php -m | grep mbstring - Windows:
php.ini中取消注释extension=mbstring,并确认extension_dir指向正确目录 - 运行时检测:
var_dump(get_loaded_extensions());查看输出中是否有mbstring
别信 mb_detect_encoding(),源头编码必须明确
用户输入、数据库读取、API 响应的编码不能靠“探测”——mb_detect_encoding($str) 在 PHP 7.2 中准确率极低,尤其对短中文字符串常误判为 ASCII:
- 表单提交:确保 HTML 有
<meta charset="UTF-8">,且 POST 请求头为Content-Type: application/x-www-form-urlencoded; charset=UTF-8 - MySQL 连接:执行
SET NAMES utf8mb4,且 PDO/MySQLi 初始化时指定PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4" - 文件读取:
file_get_contents()返回内容需确认原始文件保存为 UTF-8 无 BOM
遇到 mb_strlen() 仍返回异常值?先查隐藏字符
看似干净的中文字符串,可能混入零宽空格(\xe2\x80\x8b)、软连字符(\xc2\xad)、BOM(\xef\xbb\xbf)等不可见字符,导致长度虚高:
- 快速诊断:
echo bin2hex($str);查看十六进制字节流,中文 UTF-8 应为连续的e4-b8-80类三字节序列,夹杂efbbbf或e2808b就是脏数据 - 清理建议:
$clean = preg_replace('/[\x{200b}-\x{200f}\x{202a}-\x{202f}\x{feff}]/u', '', $str); - 更彻底方案:
$clean = mb_convert_encoding($str, 'UTF-8', 'UTF-8');(第二个UTF-8表示源编码,强制重编码可剔除非法序列)
真正容易被忽略的点是:PHP 7.2 的 mbstring 默认编码不可靠,且所有用户输入渠道都必须统一为 UTF-8 —— 编码不一致时,mb_strlen() 给出的数字再“对”,也和数据库字段限制、前端显示、正则匹配对不上。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











