mb_strcut按字节截取但自动对齐字符边界,避免乱码;substr纯字节截取,易截断多字节字符导致解码失败。

mb_strcut 能截断到完整字符边界,是因为它按字节操作但**感知多字节编码结构**,内部会检查截断位置是否落在某个 UTF-8(或其他指定编码)字符的中间。如果发现要切的位置卡在 2 字节、3 字节或 4 字节 UTF-8 字符的中间(比如只取了前 1 个字节),它就自动回退到该字符的起始字节,确保返回的子串不包含“半个汉字”或乱码字节序列。
它和 substr 的根本区别在哪
substr 是纯字节截断:给它一个 UTF-8 字符串 "你好"(共 6 字节),让它从第 0 位取 5 字节,结果就是 "你" —— 后面那个 就是被劈开的“好”字首字节单独成块,解码失败。
mb_strcut 则会扫描这 5 字节末尾:发现第 5 字节属于一个 3 字节 UTF-8 字符的中间位置,于是往前找到这个字符真正的开头(第 4 字节),只取前 4 字节,即完整的“你”,不拼凑残缺字符。
它依赖编码声明才能正确工作
mb_strcut 不是“自动识别编码”,它需要明确知道当前字符串用的是什么编码:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
立即学习“PHP免费学习笔记(深入)”;
- 默认使用 mb_internal_encoding() 设置的编码(通常是 UTF-8)
- 也可以显式传入第三个参数,如 mb_strcut($str, 0, 10, 'UTF-8')
- 如果误设为 'ISO-8859-1',而实际是 UTF-8,它就失去判断能力,退化为类似 substr 的行为
实际使用中要注意的细节
它不是“按字符数截取”,而是“按字节数截取,但保证不切断字符”:
- 传入长度 10,不等于得到 10 个汉字;可能只有 3 个汉字 + 几个 ASCII 字母,因为汉字占 3 字节
- 如果字符串开头就是多字节字符,且 start 偏移量落在其内部,mb_strcut 也会向前对齐到该字符起点
- 对 ASCII 字符串(单字节),它的行为和 substr 完全一致,没有额外开销
为什么 PHP 8.0 还要强调这个函数
PHP 8.0 加强了多字节函数的健壮性,比如更严格校验非法 UTF-8 序列、避免因畸形编码触发警告或静默失败。mb_strcut 在 8.0 中对边界情况(如空字符串、负偏移、超长 length)的处理更统一,减少了因编码误判导致的意外截断 —— 这让依赖它做安全截断(如日志摘要、前端显示截断)的代码更可靠。


















