本文目录导读:

在PHP中,克隆(复制)对象主要有以下几种方式:
使用 clone 关键字(浅拷贝)
class User {
public $name;
public $profile;
public function __construct($name, $profile) {
$this->name = $name;
$this->profile = $profile;
}
}
$user1 = new User('张三', ['age' => 25, 'city' => '北京']);
$user2 = clone $user1;
// 修改克隆对象
$user2->name = '李四';
$user2->profile['age'] = 30;
echo $user1->name; // 张三(不受影响)
echo $user1->profile['age']; // 30(受影响!因为对象引用被共享)
实现 __clone() 方法(深拷贝)
class User {
public $name;
public $profile;
public $address; // 对象类型属性
public function __construct($name, $profile, Address $address) {
$this->name = $name;
$this->profile = $profile;
$this->address = $address;
}
public function __clone() {
// 深拷贝对象类型属性
if ($this->address instanceof Address) {
$this->address = clone $this->address;
}
// 深拷贝数组(可选)
if (is_array($this->profile)) {
// 数组本身就是值拷贝,但如果是关联数组或嵌套数组
$this->profile = $this->deepCopyArray($this->profile);
}
}
private function deepCopyArray($array) {
$result = [];
foreach ($array as $key => $value) {
if (is_object($value)) {
$result[$key] = clone $value;
} elseif (is_array($value)) {
$result[$key] = $this->deepCopyArray($value);
} else {
$result[$key] = $value;
}
}
return $result;
}
}
class Address {
public $city;
public $street;
public function __construct($city, $street) {
$this->city = $city;
$this->street = $street;
}
}
// 使用
$address = new Address('北京', '长安街');
$user1 = new User('张三', ['age' => 25, 'city' => '北京'], $address);
$user2 = clone $user1;
$user2->address->city = '上海';
echo $user1->address->city; // 北京(不受影响,深拷贝成功)
使用序列化实现深拷贝
function deepClone($object) {
return unserialize(serialize($object));
}
// 或者使用 PHP 8.0+ 的 __serialize() 和 __unserialize()
class User implements Serializable {
public $name;
private $data;
public function serialize() {
return serialize([
'name' => $this->name,
'data' => $this->data
]);
}
public function unserialize($data) {
$arr = unserialize($data);
$this->name = $arr['name'];
$this->data = $arr['data'];
}
}
使用工厂方法模式
class User {
public $name;
public $email;
public static function from(User $user): self {
$clone = new self();
$clone->name = $user->name;
$clone->email = $user->email;
return $clone;
}
}
// 使用
$user1 = new User();
$user1->name = '张三';
$user2 = User::from($user1);
完整示例:处理各种复杂情况
class SerializableObject {
private $resources = [];
public function __clone() {
// 清理资源
foreach ($this->resources as &$resource) {
// 重新分配资源
}
// 复制其他属性
foreach (get_object_vars($this) as $property => $value) {
if (is_object($value)) {
$this->$property = clone $value;
}
}
}
}
注意事项
-
浅拷贝 vs 深拷贝
clone默认是浅拷贝,只复制对象本身- 需要手动处理对象类型属性的克隆
-
不可克隆对象
class Singleton { private function __clone() { throw new \Exception('Cannot clone singleton'); } } -
循环引用处理
class Node { public $next; public $value; public function __clone() { if ($this->next !== null) { $this->next = clone $this->next; } } }
选择哪种方式取决于你的具体需求:
- 简单对象:直接用
clone - 复杂对象:实现
__clone()方法 - 需要完全独立:使用序列化/反序列化
- 定制化克隆:使用工厂方法
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播