判断函数可用性需分层验证:内置函数用function_exists(),语言特性用version_compare(PHP_VERSION, 'x.y.0', '>='),扩展函数先extension_loaded()再function_exists();替代方案重在避免fatal error而非功能模拟。

PHP函数不是写完就能跑通的,版本一换,http_response_code() 可能直接报错,str_contains() 在 7.4 以下根本不存在,is_readonly() 是 8.7 才加的。别指望“差不多能用”,得按版本精准匹配。
怎么判断函数是否存在且可用
不能只靠 function_exists(),它对语言结构(如 match)、魔术常量、扩展函数都不可靠;也不能只看 PHP 主版本号,比如 str_starts_with() 是 8.0 加的,但 str_contains() 要等到 8.1。
- 优先用
function_exists('str_contains')检查内置函数,但注意:它对array_key_first()(7.3+)或get_debug_type()(8.0+)这类“存在即可用”的函数有效 - 对语言级特性(如
match、enum),必须用version_compare(PHP_VERSION, '8.0.0', '>='),PHP_VERSION比phpversion()更快且无副作用 - 对扩展函数(如
mysqli_connect()),先extension_loaded('mysqli'),再function_exists('mysqli_connect'),避免扩展加载失败却误判函数可用
低版本替代高版本函数的实操写法
硬升级 PHP 不现实时,得靠兜底逻辑。重点不是“模拟功能”,而是“避免 fatal error”。
-
str_contains($haystack, $needle)(8.1+)→ 改用strpos($haystack, $needle) !== false,注意strpos对空字符串返回 0,要显式判false -
http_response_code(404)(5.4+)→ 先version_compare(PHP_VERSION, '5.4.0', '>='),否则用header('HTTP/1.1 404 Not Found') -
array_key_first($arr)(7.3+)→ 低版本用key($arr),但需确保$arr非空且已重置内部指针(reset($arr)) -
throw_if($condition, InvalidArgumentException::class, 'msg')(8.7+)→ 直接if ($condition) throw new InvalidArgumentException('msg');,无需封装
PHP 8.7 新函数的使用边界
刚发布的 is_readonly()、str_contains_any() 看着好用,但实际部署时容易踩坑:它们不是“全量可用”,而是依赖具体构建配置和扩展状态。
立即学习“PHP免费学习笔记(深入)”;
-
is_readonly($obj, 'prop')只对 PHP 8.7 编译时启用了zend.enable_readonly_properties的环境生效;若该 ini 项被禁用,函数始终返回false,不报错也不警告 -
str_contains_any($str, ['a','b'])在 8.7.0 RC 版本中存在内存泄漏,正式版修复,但 CI 流水线若还跑着 RC 镜像就会出问题 -
array_validate($arr, 'int')对嵌套数组无效,只校验一级元素;想深度校验得自己递归调用,或改用filter_var_array()+ 自定义回调
最麻烦的不是函数有没有,而是它在什么条件下“看似存在却行为异常”——比如 strlen(null) 在 8.1+ 报 deprecated,但在 8.0 下静默返回 0;这种隐性差异比直接报错更难定位。



















