php 8.3 判断字符串长度必须用 mb_strlen($str, 'utf-8'),禁用 strlen;需确保 mbstring 启用、全链路 utf8mb4 对齐、入库前字符与字节数双重校验,并清理隐藏字符。

PHP 8.3 判断字符串长度,核心是**统一按字符计数 + 全链路 UTF-8(utf8mb4)对齐**,而不是依赖默认字节行为。只要编码环境干净、函数用对、校验逻辑完整,就不会出错。
必须用 mb_strlen(),且显式指定 'UTF-8'
PHP 8.3 仍默认把字符串当字节流处理。strlen("你好") 返回 6,这不是 bug,是设计如此——但它在中文、emoji 场景下完全不可用于业务逻辑。
- 所有长度判断(如表单校验、截断前检查、API 入参限制)一律改用 mb_strlen($str, 'UTF-8')
- 不要省略第二个参数:mb_strlen($str) 可能 fallback 到 internal_encoding,默认可能是 ISO-8859-1,结果错得更隐蔽
- 确认 mbstring 扩展已启用:运行 php -m | grep mbstring 或查看 phpinfo() 中的 mbstring 模块状态
入库前做双重校验:字符数 + 字节数估算
MySQL 的 VARCHAR(255) 是按字符限制,但 utf8mb4 下一个 emoji 占 4 字节。只看字符数不够保险,尤其字段实际字节上限可能受限于连接或列定义。
- 先用 mb_strlen($str, 'UTF-8') 确认没超字符上限(比如 ≤255)
- 再算最大可能字节数:mb_strlen($str, 'UTF-8') * 4,和字段真实字节容量比对(如 utf8mb4 下 VARCHAR(255) 最多 1020 字节)
- 入库前加一层标准化:mb_convert_encoding($str, 'UTF-8', 'UTF-8'),可清除非法序列、修复隐式乱码
警惕隐藏字符和粘贴污染
用户从微信、网页复制的文字常带零宽空格(U+200B)、软连字符(U+00AD)、BOM 头等不可见字符,trim() 对它们无效,导致 strlen/mb_strlen 结果偏大。
- 快速排查:用 bin2hex($str) 查看原始字节,找 e2808b(零宽空格)或 c2ad(软连字符)这类异常序列
- 清理建议:preg_replace('/[\x{200B}\x{200C}\x{200D}\x{00AD}]/u', '', $str),或更通用的控制符过滤
- 关键操作前强制转码:mb_convert_encoding($str, 'UTF-8', 'UTF-8') 能自动丢弃非法字节并归一化
数据库与连接层必须全 utf8mb4
PHP 层算得再准,如果 MySQL 连接用的是 latin1,或者表字段其实是 utf8(非 utf8mb4),那插入时照样被截断或报错,且错误发生在 SQL 层,PHP 完全感知不到。
- PDO 连接时加上 charset=utf8mb4:new PDO("mysql:host=...;charset=utf8mb4", ...)
- 建表语句确认字符集:SHOW CREATE TABLE table_name,Collation 应为 utf8mb4_unicode_ci 或类似
- 避免用 SET NAMES utf8 —— 必须用 SET NAMES utf8mb4,否则 emoji 会被截成问号或报错
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











