str_contains_safe() 函数兼容 PHP7.4 和 PHP8,通过强制字符串转换、空值兜底、严格比较及 mbstring 降级策略,确保行为一致且无警告。

直接封装一个兼容 PHP7.4 和 PHP8 的字符串搜索函数,核心是避开版本差异、统一行为、不依赖新语法。关键不是重写逻辑,而是选对函数、做稳判断、补足边界。
用 strpos() + 严格比较,不碰 str_contains()
PHP 8.0 新增了 str_contains(),但 PHP7.4 没有,不能直接用。继续用 strpos() 是最稳妥的选择,只需注意返回值判断方式:
- 必须用
!== false,不能用== true或!empty()—— 因为子串在开头时返回0,弱比较会误判 - 确保两个参数都是字符串:若传入数字(如
strpos($text, 1)),PHP 会隐式转成字符串,但易引发歧义(比如匹配 "10" 也会命中 "1"),建议提前(string)$needle
封装时加一层空值和类型防护
PHP8 对未定义变量、null 传给字符串函数更敏感(可能触发 Warning 或 TypeError),而 PHP7.4 容忍度高。封装时主动兜底:
- 对
$haystack做空值处理:$haystack = (string)($haystack ?? '') - 对
$needle同样转字符串并判空:$needle = (string)($needle ?? '');若为空字符串,可直接返回true(按语义,空串视为存在于任意字符串中) - 避免传
null或数组进去,否则 PHP8 下strpos(null, 'a')会报TypeError
支持多字节字符的可选增强版
如果项目涉及中文、emoji 等,基础 strpos() 按字节匹配,可能出错(如在 UTF-8 中跨字节截断)。此时可封装带 mbstring 支持的版本,但需运行时检测:
立即学习“PHP免费学习笔记(深入)”;
- 先检查
function_exists('mb_strpos')和extension_loaded('mbstring') - 存在则调用
mb_strpos($haystack, $needle, 0, 'UTF-8'),并同样用!== false判断 - 不存在则回落到原生
strpos()—— 这种降级策略让函数在无 mbstring 环境下仍可用,只是不保证多字节安全
最终封装示例(可直接复用)
这个函数在 PHP7.4 和 PHP8.0+ 下行为一致,无 Fatal Error,也无隐式警告:
function str_contains_safe($haystack, $needle): bool
{
$haystack = (string)($haystack ?? '');
$needle = (string)($needle ?? '');
if ($needle === '') {
return true;
}
if (function_exists('mb_strpos') && extension_loaded('mbstring')) {
return mb_strpos($haystack, $needle, 0, 'UTF-8') !== false;
}
return strpos($haystack, $needle) !== false;
}



















