本文目录导读:

在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()方法 - 需要完全独立:使用序列化/反序列化
- 定制化克隆:使用工厂方法