PHP 8.1+ 要求 substr() 第一参数为非空字符串,传 null 会触发弃用警告并可能升级为致命错误;必须用 is_string() 显式判空后调用,或封装 safe_substr() 统一处理,同时排查上游 null 来源并检查其他同类字符串函数。

直接在调用 substr() 前加类型判断,确保第一个参数($string)不是 null。PHP 8.1+ 将该参数声明为非空 string,传 null 会触发弃用警告,不处理会在后续版本升级中变成致命错误。
先判空再调用
这是最常用也最稳妥的修复方式。不能依赖函数内部容错,必须主动拦截 null。
- 用
is_string()或isset()+is_string()组合判断 - 避免只用
empty()或!$var,它们对"0"、0、false等也会返回真,可能误伤有效字符串 - 如果业务允许,可用空字符串
''作为兜底值
示例:
// ❌ 错误写法
$result = substr($input, 0, 10);
// ✅ 正确写法:显式判空
if (!is_string($input)) {
$result = '';
} else {
$result = substr($input, 0, 10);
}
// ✅ 或更简洁(适合单行场景)
$result = is_string($input) ? substr($input, 0, 10) : '';
统一收口处理 null 输入
如果项目中多处使用 substr() 且来源不可控(如数据库字段、API 返回、配置项),建议封装一个安全版本。
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 封装函数可复用逻辑,避免各处重复判空
- 可选支持默认返回值或抛出异常,便于调试定位源头
- 注意不要覆盖原生函数名,避免歧义
示例:
function safe_substr(string $string = '', int $offset = 0, ?int $length = null): string
{
return substr($string, $offset, $length);
}
// 调用时自动兜底
$result = safe_substr((string)$input, 0, 10);
排查 null 来源并前置修正
警告只是表象,null 往往来自上游逻辑——比如数据库字段允许 NULL、模型 getter 没设默认值、API 接口未做字段校验等。
- 检查调用
substr()的变量是从哪来的:是 DB 查询结果?是 request 参数?是缓存反序列化? - 如果是 Eloquent 模型字段,可在
getAttributes()或访问器中强制转字符串 - 如果是 API 输入,应在请求验证层(Request 类或中间件)统一转换或拒绝
别忽略其他类似函数
substr() 不是孤例。PHP 8.1+ 对 strpos()、strlen()、str_replace()、trim() 等数十个内置字符串函数都加了非空类型约束。
- 搜索代码中所有这些函数的调用点,批量检查参数是否可能为
null - 可以用正则快速扫描:
\bsubstr\s*\(\s*\$[a-zA-Z0-9_]+\s*,或结合 PHPStan/psalm 静态分析 - 重点盯防从数据库、JSON 解码、用户输入直传过来的变量
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










