php 8.5 引入的 clone with 语法允许在克隆对象的同时直接修改其属性,无需先调用 __clone() 方法或手动赋值。具体做法是在 clone 关键字后使用 with 块,在花括号内指定要覆盖的属性及其新值,该语法会自动处理浅拷贝后的属性覆写。

基本语法的结构是怎样的
基本结构由 clone 关键字、源对象变量和 with 代码块组成。在 with 块中,你可以列出需要更改的属性名和对应的值,这些属性必须存在于目标类中。执行时,PHP 会先创建对象的副本,然后按顺序应用 with 块中的修改。

<?php class User {
public string $name;
public int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
$original = new User('Alice', 30);
// 克隆并修改 name 属性
$newUser = clone $original with (
name: 'Bob'
);
echo $newUser->name; // 输出 Bob
echo $newUser->age; // 输出 30 (保持不变)
?>
预期结果:
1. $newUser->name 为字符串 'Bob'。
2. $newUser->age 为整数 30。
3. $original 对象未受影响。
如何处理嵌套对象或复杂类型
当属性是对象或数组等复杂类型时,clone with 依然遵循浅拷贝原则。如果希望修改嵌套对象的属性,需要在 with 块中重新赋值整个嵌套对象,或者确保该属性支持链式修改。对于标量类型,直接赋值即可生效。
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。

<?php class Address {
public string $city;
public function __construct(string $city) {
$this->city = $city;
}
}
class Person {
public string $name;
public Address $address;
public function __construct(string $name, Address $address) {
$this->name = $name;
$this->address = $address;
}
}
$addr = new Address('New York');
$person = new Person('Charlie', $addr);
// 克隆并修改嵌套的 Address 对象
$newPerson = clone $person with (
address: new Address('Los Angeles')
);
echo $newPerson->address->city; // 输出 Los Angeles
echo $person->address->city; // 输出 New York
?>
预期结果:
1. $newPerson->address->city 为 'Los Angeles'。
2. $person->address->city 保持 'New York'。
3. 两个 Address 对象是不同的实例。
如果在 with 块中引用了不存在的属性会发生什么
如果在 with 块中尝试设置一个未在类中定义的属性,PHP 会抛出 Error 异常,提示属性不存在。这确保了类型安全,防止意外创建动态属性。开发者必须确保 with 块中的所有属性键都是目标类中已声明的公共属性。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










