PHP 8.6 升级自查笔记:三十项弃用里,哪些会改变现有代码的行为
PHP 8.6 计划于 2026 年 11 月 19 日发布,变更规模比 8.5 更小:没有 JIT 变更,没有属性钩子(property hooks),没有联合类型——没有任何会重塑类编写方式的改动。这一版真正的主题是大约三十项弃用,它们都在为 PHP 9.0 的移除铺路。
新增内容只有两项值得一提:部分函数应用,以及 final readonly class Time\Duration(35 票赞成、1 票反对),让超时能够携带自己的单位。
下面按「会不会改变运行时行为、要不要动现有代码」来逐项核对。
会直接改变运行时行为
- 从
finally块中返回:已弃用,39 票对 3 票,是整个弃用 RFC 中票数最悬殊的一项。从finally中返回一直都非常令人困惑,是微妙 bug 的根源。 - 从
__construct()或__destruct()返回值:已弃用。 - 把对象当数组传给函数:一些函数在接收数组的同时也接受对象,例如
array_walk()、array_walk_recursive()、deflate_init()、inflate_init()、zlib 与 bzip2 流过滤器参数、mb_convert_variables()以及http_build_query()。其内部实现方式可能导致微妙的 bug,甚至造成内存损坏。修复方式几乎总是在调用处加上get_object_vars($obj)。 - 通过反射在真实对象上进行静态调用:已弃用。
- 使用错误类型设置
ReflectionProperty值:已弃用。
需要在调用处改写
is_a()与is_subclass_of()以字符串作为第一个参数已弃用(即$allow_string为 false 时)。define()的$case_insensitive参数已弃用。- 排序函数的
SORT_LOCALE_STRING标志已弃用。 ArrayIterator中那些继承而来却毫无意义的方法、SplFileObject的 CSV 方法,以及不完整的session_set_save_handler()实现,同样已被弃用。
标识符与保留词汇
readonly作为函数名已弃用(39 票对 1 票)。readonly最初被允许用作函数名,是因为 WordPress 有一个同名函数,这是通过 PHP 词法分析器中的一个 hack 实现的。is与let作为标识符、namespace作为类常量名,以及_作为常量,均已被弃用。引擎正在保留词汇——尤其是is,它被留作未来模式匹配之用。
函数级弃用
is_double、is_integer、is_long、doubleval、strcoll、metaphone、spl_classes、spl_object_hash、mysqli::stmt_init、mysqli_get_charset。
mb_ereg 系列:语义迁移,不是重命名
Oniguruma——mbstring 的 mb_ereg 系列背后的正则引擎——已于 2025 年 4 月 24 日停止上游维护。PHP 的回应是:8.6 中弃用,PHP 9.0 中移除。如果正在使用 mb_ereg()、mb_eregi()、mb_ereg_replace()、mb_regex_encoding() 及其同族函数,应转向 PCRE,即使用带 /u 修饰符的 preg_*。这是语义迁移,而不是重命名;两个引擎在足够多的细节上存在分歧,因此每迁移一个模式都应配套测试。
把弃用清单当路线图读
这些弃用项作为路线图来读异常清晰:内部开发者正在为模式匹配保留关键字,剥离一个失去维护的正则引擎,终结「对象当数组用」的时代,把警告变成异常,并收紧安全默认值。