编程 finally 里 return、is_long、spl_object_hash:PHP 8.6 弃用清单里最该先清理的几类调用

2026-10-27 21:02:28

PHP 8.6 弃用清单:升级时最容易一起爆的几类调用与替换写法

来源:PHP RFC: Deprecations for PHP 8.6(wiki.php.net/rfc/deprecations_php_8_6,Status: Pending Implementation,Implementation: 8.6)。PHP 8.6 计划 2026-11-19 GA。

这里有个关键的时间差:这些改动在 8.6 只报 deprecated,到 9.0 才真正移除。所以错误日志会先响很久,真正致命要等 9.0;但 deprecation 是唯一可以一直推迟、最后在升级时一次性全部触发的改动,现在清理成本最低。

8.6 的提示消息里会直接给替代项,例如:

Function is_long() is deprecated since 8.6, use is_int() instead
Function spl_object_hash() is deprecated since 8.6, consider using spl_object_id() instead
Constant SORT_LOCALE_STRING is deprecated since 8.6, use one of the Collator::*sort*() methods instead
Method SplFileObject::fgetcsv() is deprecated since 8.6

最快拿到一份完整清单的方法:CI 里换成 8.6 跑一遍测试套件,把 E_DEPRECATED 全部收集起来,再按下面对应处理。

从 finally 块 return

在 finally 里 return 会吞掉异常。替代写法:把 return 移到 try/catch 的正常路径上,finally 只保留清理逻辑。

grep -rn -A6 'finally' --include='*.php' .

这条很难靠工具自动改,只能把候选列出来人工过。

类型别名:is_long / is_integer / is_double / doubleval

替代关系固定:is_long()、is_integer() → is_int(),is_double() → is_float(),doubleval() → floatval()。

grep -rnE '\b(is_long|is_integer|is_double|doubleval)\s*\(' --include='*.php' .

纯改名,可以直接批量替换。把 PHPStan 的 phpVersion 设为 80600 后,这类调用也会按 deprecated 报出来;在代码库中开启 reportUnmatchedIgnoredErrors 之后,可以把它当成检查的一部分。

spl_object_hash()

替代是 spl_object_id()。注意两者返回值不同:spl_object_hash() 给出 32 位十六进制字符串,spl_object_id() 是 int。如果 hash 被写进缓存键、文件名或数据库字段,不能直接换。

grep -rn 'spl_object_hash' --include='*.php' .

strcoll() 与 SORT_LOCALE_STRING

替代是 intl 扩展的 Collator::compare() 与 Collator::*sort*()(如 Collator::asort)。如果项目没装 intl,得先补扩展,这一步建议提前确认。

grep -rnE '\bstrcoll\s*\(|SORT_LOCALE_STRING' --include='*.php' .

SplFileObject 的 CSV 方法

SplFileObject::fgetcsv()、fputcsv() 等被弃用。替代:走 str_getcsv($file->fgets()),或换回普通文件句柄上的 fgetcsv() / fputcsv()。

grep -rnE 'SplFileObject|->fgetcsv\(|->fputcsv\(' --include='*.php' .

mysqli_stmt_init()

替代是直接构造:$stmt = new mysqli_stmt($mysqli);。日常更常见的是直接用 $mysqli->prepare()。

grep -rn 'mysqli_stmt_init' --include='*.php' .

把对象当数组传

array_walk() / array_walk_recursive() 的 $array、http_build_query() 的 $data,同样受影响的还有 mb_convert_variables() 的 $vars、deflate_init() / inflate_init() 的 $options,以及 zlib.inflate / zlib.deflate、bzip2.compress / bzip2.decompress 流过滤器参数。

替代写法是显式转换:array_walk((array) $obj, ...) 或 get_object_vars($obj),不要依赖隐式转换。

grep -rnE '(array_walk|array_walk_recursive|http_build_query|mb_convert_variables)\s*\(' --include='*.php' .

grep 只能给出候选;这一类主要靠 PHPStan / Psalm 的参数类型检查抓出来——把对象传给声明为 array 的参数会直接报错,比 grep 准确得多。

同一份 RFC 里还有 Reflection 相关、define() 的 $case_insensitive、session_set_save_handler() 的 handler 缺少 create_sid()/validateId() 等条目,升级前应当对照 RFC 一起检查,避免到 9.0 才暴露这些问题。

复制全文 生成海报 PHP 版本升级 代码迁移

推荐文章

程序员茄子在线接单