PHP 8.5 新语法实战:clone-with、管道操作符与 #[NoDiscard]
PHP 8.5 于 2025-11-20 发布。下面是 clone-with、管道操作符 |>、#[NoDiscard] 的语法笔记,代码均按 8.5 语法编写。
clone-with:克隆并覆盖属性
从 PHP 8.5 起,clone 可以按函数形式使用,并接受第二个可选参数:命名属性关联数组。键是属性名,值是覆盖后的新属性值。
readonly class Color
{
public function __construct(
public int $red = 0,
public int $green = 0,
public int $blue = 0,
public int $alpha = 255,
) {}
}
$base = new Color(red: 1, green: 2, blue: 3);
$next = clone($base, ['red' => 200, 'alpha' => 128]);
echo $base->red; // 1
echo $next->red; // 200
echo $next->alpha; // 128
对 readonly 类来说,这就是一个内置的 with-er:想生成一个“只改几个属性”的新对象时,不必为每个字段手写 withRed()、withAlpha(),也不必用 new self(...) 把全部旧值重列一遍。
注意语法是函数式调用:
$new = clone($obj, ['prop' => newValue]);
不是 clone $obj with [...],PHP 没有那种语法。
管道操作符 |>:组合 first-class callable
|> 把左侧值作为第一个参数传给右侧可调用对象。右侧推荐使用 first-class callable,例如 trim(...)。
之前嵌套的写法:
$result = strtoupper(trim($input));
用管道后变成从左到右读:
$result = $input |> trim(...) |> strtoupper(...);
多步变换示例:
$input = " PHP 8.5 pipe \n";
$result = $input |> trim(...) |> strtolower(...) |> htmlspecialchars(...);
echo $result; // php 8.5 pipe
右侧要写 trim(...) 这样的 first-class callable,不是裸函数名 trim。
#[NoDiscard]:返回值必须使用
在函数或方法上标注 #[NoDiscard] 后,调用方如果忽略其返回值,会触发告警。
#[NoDiscard]
function acquireLock(): bool
{
return true;
}
acquireLock(); // 触发 warning:返回值未被使用
显式表示“我就是要放弃返回值”时,用 (void) 包住调用:
(void) acquireLock(); // 不触发 warning
适合用在那些“看返回值才能确认成功”的 API 上,例如加锁、写文件、保存数据。
生产建议
生产环境升级建议等 8.5.1。这些语法改动可以先在本地 PHP 8.5 开发环境验证。