PHP 8.0 中文安全截取函数需强制多字节处理、显式声明UTF-8编码、前置空值与类型校验,支持省略号补全且不截断字符,推荐使用带类型注解的 safe_mb_substr() 实现。

PHP 8.0 封装中文安全截取函数,核心不是“怎么切”,而是“怎么不乱码、不截断、不越界、不崩”。关键在三点:强制多字节处理、显式编码声明、边界容错兜底。直接用 substr() 切中文会丢字、出问号,必须用 mb_substr() 并配对校验。
必须指定 UTF-8 编码,且显式传参
mb_substr() 默认使用内部编码(可能为 ISO-8859-1),不设编码等于裸奔。即使项目全局设了 mb_internal_encoding('UTF-8'),也不能依赖——函数内必须显式传第四个参数:
- ✅ 正确:
mb_substr($str, 0, 10, 'UTF-8') - ❌ 危险:
mb_substr($str, 0, 10)(编码不确定,线上环境可能突变) - ⚠️ 注意:
'UTF-8'是字符串字面量,不能写成UTF8或utf8(大小写敏感,且必须带引号)
长度校验与空值防护要前置
输入可能是 null、空字符串、非字符串类型(如数组、对象)。PHP 8.0 的联合类型可帮上忙,但运行时仍需判断:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 先用
is_string($str) && $str !== ''过滤非法输入,避免mb_strlen()报 Warning - 截取长度
$length必须 ≥ 0,负数直接返回空字符串或抛InvalidArgumentException - 若
$length >= mb_strlen($str, 'UTF-8'),直接返回原串,不调用mb_substr(省一次计算)
支持省略号补全,且不破坏末尾字符
加 … 很常见,但不能简单拼接——否则可能把半个汉字+省略号一起输出(如“北…”实为“北京”的“京”被截半)。安全做法是:先按目标长度减去省略号占位(通常 1 个 Unicode 字符),再截取,最后追加:
立即学习“PHP免费学习笔记(深入)”;
- 例如要截 10 字 +
…:实际取前mb_substr($str, 0, 9, 'UTF-8'),再拼… - 省略号本身也需用 UTF-8 编码,推荐用 Unicode 字面量
"\u{2026}"或直接写'…'(确保文件保存为 UTF-8) - 若原字符串已 ≤ 目标长度,不加省略号
完整推荐实现(带类型注解)
以下函数可直接放入工具类或公共函数文件,PHP 8.0+ 原生支持:
function safe_mb_substr(string $str, int $length, string $encoding = 'UTF-8', bool $appendEllipsis = false): string{
if ($length return '';
}
if ($str === '' || !is_string($str)) {
return '';
}
$actualLen = mb_strlen($str, $encoding);
if ($length >= $actualLen) {
return $str;
}
$cutLen = $appendEllipsis ? $length - 1 : $length;
$cutLen = max(0, $cutLen);
$result = mb_substr($str, 0, $cutLen, $encoding);
return $appendEllipsis ? $result . '…' : $result;
}
?>


















