PHP 8.5 语言层改动:|> 管道、clone with、#[\NoDiscard] 与常量表达式闭包
PHP 8.5.0 已于 2025-11-20 发布。这里只梳理语言层面的新增与调整,信息来自 php.net 的 Release Announcement、New Features 手册与 php-src 的 UPGRADING,以及 zend.com 的《PHP 8.5: New Features and Deprecations》。
管道操作符 |>
|> 把可调用对象从左到右串起来,值在多个函数之间依次传递,不需要再声明中间变量。它替代的是那种由内向外读的嵌套调用,链式写法可以顺着念。
$result = "hello" |> strtoupper(...) |> strrev(...);
RFC:pipe-operator-v3(作者 crell)。
clone with
克隆对象时现在可以同时更新属性:clone() 接受一个可选的第二参数,是一个关联数组,给出要设置在克隆体上的具名属性及取值。对 readonly 属性较多的类,这类「with-er」模式写起来简单了不少。
#[\NoDiscard] 与 (void) 强转
给函数加上 #[\NoDiscard] 之后,PHP 会检查返回值是否被消费,没用到就告警。适合那种「返回值很重要、但很容易忘了用」的 API。
配套新增 (void) 强转,用来显式声明「这个值我故意不用」,可以抑制 #[\NoDiscard] 的告警,也可能抑制外部 IDE 与静态分析工具的同类诊断。
RFC:marking_return_value_as_important。
常量表达式里的闭包与一等可调用
静态闭包和一等可调用(first-class callables)现在可以出现在常量表达式里,包括属性参数、属性默认值、参数默认值、常量与类常量。
另外注意:Closure 现在是 callable 的正式子类型。
RFC:closures_in_const_expr、fcc_in_const_expr。
其他语言层改动
- 致命错误(例如超过最大执行时间)现在会带上 backtrace。RFC:
error_backtraces_v2。 - 属性可加在编译期非类常量上,即
const MY_CONST = 1;这种,而不是define();#[\Deprecated]现在也能用于常量和 trait。 #[\Override]可以作用在属性上:引擎会校验父类或所实现接口中是否存在同名属性,不存在就编译报错。RFC:override_properties。- 静态属性支持非对称可见性(asymmetric visibility)。RFC:
static-aviz。 - 用构造器属性提升时可以声明
final属性。RFC:final_promotion。 - 常量表达式里支持 cast。
- 新增
#[\DelayedTargetValidation]:抑制核心/扩展属性用在无效目标上时的编译期错误,把报错推迟到运行时调用ReflectionAttribute::newInstance()。 - OpCache 成为非可选部分,始终存在于二进制中。
弃用与移除(节选)
- 非规范的标量类型 cast 名
(boolean)、(double)、(integer)、(binary)弃用。 mysqli_execute别名弃用;curl_close、curl_share_close、xml_parser_free弃用(在 PHP >= 8.0 中它们已经是 no-op);socket_set_timeout弃用;MHASH_*常量全部弃用。- 非数字字符串的自增/自减弃用(Increment/Decrement operators RFC,Girgias)。
get_defined_functions()的$exclude_disabled参数弃用;array_key_exists()用null当数组偏移等用法弃用。- CLI/CGI 的
-z/--zend-extension选项移除。 - CLI 新增
php --ini=diff,输出非默认的 INI 指令。