PHP 8.5 定稿:|> 管道、clone 带 with、#[\NoDiscard],以及一个箭头函数优先级坑
PHP 8.5 于 2025-11-20 GA。相对 8.4,这次变化集中在语法、常量表达式和几个扩展上。以下按落地方式逐条记录。
|> 管道操作符
RFC:pipe-operator-v3。它把左侧的值作为右侧 callable 的参数,从左到右串起来,用来替代嵌套调用:
$result = "hello" |> strtoupper(...) |> trim(...);
strtoupper 的结果会继续传给 trim。写法上用的是 first-class callable 语法 strtoupper(...)。
有一条 2025-08-28 修订的 errata 必须记住:管道链里如果某一步是箭头函数 fn(),必须加括号,否则箭头函数会一直“吞掉”后续内容直到表达式结尾——这是解析优先级造成的。函数名、变量、first-class closure、一等可调用对象作为管道步骤时不受影响。
另外,关联的 compose 操作符(延迟组合)被拆到后续 RFC,这次落地的 pipe 只做立即执行。
clone 变成函数,支持 $withProperties
clone 现在可以当函数调用,并接受第二个参数 $withProperties,在克隆时重写属性:
$b = clone($a, ['x' => 1]);
这个形态主要是给 readonly 类做 “with-er” 模式用的。
#[\NoDiscard]
用这个属性标注函数返回值必须被消费。返回值被忽略时会告警。配合新增的 (void) 强制转换,可以显式表示“故意丢弃”。(void) 本身不影响执行,只是告诉编译器这个丢弃是有意的。
闭包与一等可调用进入常量表达式
闭包和一等可调用现在可以出现在常量表达式里,包括:属性参数、属性/参数默认值、常量。
其他新增
- 新增
uri扩展,默认启用,按 RFC 3986 + WHATWG URL 实现。 - 新增
array_first()/array_last()。 setcookie/setrawcookie支持partitioned(CHIPS)。- fatal error 会带上 backtrace。
#[Override]现在可以用在属性上。
持久化 cURL share handle
curl_share_init_persistent() 创建的 share handle 不再随请求销毁,可以跨请求复用,省掉重复初始化。同时 curl_getinfo 新增 used_proxy、httpauth_used、proxyauth_used 三个可查询字段。
升级来源
- php.net/releases/8.5/en.php
- 官方 NEWS(php-8.5.0)