PHP 8.1+ 中 substr() 接收 null 会抛出 TypeError 致命错误,因参数 $string 类型声明为 string;修复需用 is_string() 显式校验,避免强制转换或 ?? "" 等语义失真方式。

PHP 8.1+ 中 substr() 接收 null 参数会直接抛出 TypeError(不是警告,而是致命错误),因为其第一个参数 $string 的类型声明为 string,不可为空。这和 strpos() 的弃用警告不同,是硬性类型拦截,脚本会中断执行。
根本原因:参数类型严格化
PHP 8.1 起,substr(string $string, int $offset, ?int $length = null): string 明确要求 $string 必须是字符串。传入 null、false、0、[] 等非字符串值,都会触发:
安全修复:先校验再调用
不能依赖“默认转空字符串”或静默转换——PHP 8.1 不再容忍。必须显式确保变量是字符串:
-
推荐写法(健壮):用
is_string()判断,只在确认为字符串时调用 -
避免强制转换:如
(string)$var会把null变成"",但也会把false→""、0→"0",可能掩盖业务逻辑错误 -
不建议用 ?? "":虽然能防止报错,但会把所有非字符串都当作空字符串处理,语义失真(例如
false和""在业务中含义通常不同)
典型修复示例
假设你从数据库或 API 获取一个字段,可能为 null:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
立即学习“PHP免费学习笔记(深入)”;
$title = $post->getTitle(); // 可能返回 null $short = substr($title, 0, 50); // ❌ PHP 8.1+ 直接报错
✅ 正确做法:
$title = $post->getTitle(); $short = is_string($title) ? substr($title, 0, 50) : ''; // 或抛异常、记录日志、返回默认值
如果需要统一兜底,可封装为小函数:
function safe_substr(?string $str, int $offset, ?int $length = null): string {
return is_string($str) ? substr($str, $offset, $length) : '';
}
延伸提醒:其他字符串函数同理
strlen()、strtoupper()、trim()、str_replace() 等绝大多数字符串函数在 PHP 8.1+ 都已强化类型约束。只要参数声明为 string,传 null 就会 TypeError。统一策略就是:调用前做 is_string() 检查,不跳过、不假设、不靠强制转换蒙混过关。


















