PHP对象深拷贝与浅拷贝机制
PHP的对象赋值是引用传递,clone是创建副本。深拷贝和浅拷贝的区别在处理嵌套对象时很重要。今天说说PHP中的对象拷贝。
对象的赋值是引用。
```php
class User
{
public function __construct(
public string $name,
public Address $address
) {}
}
class Address
{
public function __construct(
public string $city
) {}
}
$addr = new Address('北京');
$u1 = new User('张三', $addr);
$u2 = $u1; // 引用同一个对象
$u2->name = '李四';
echo "u1: {$u1->name}\n"; // 李四
echo "u2: {$u2->name}\n"; // 李四
?>
浅拷贝用clone。
```php
$u1 = new User('张三', new Address('北京'));
$u2 = clone $u1;
$u2->name = '李四';
echo "u1: {$u1->name}\n"; // 张三(基本类型深拷贝)
$u2->address->city = '上海';
echo "u1: {$u1->address->city}\n"; // 上海(引用类型浅拷贝)
?>
深拷贝用__clone实现。
```php
class User2
{
public function __construct(
public string $name,
public Address $address
) {}
public function __clone(): void
{
// 深拷贝内部的引用类型
$this->address = clone $this->address;
}
}
$u1 = new User2('张三', new Address('北京'));
$u2 = clone $u1;
$u2->address->city = '上海';
echo "u1: {$u1->address->city}\n"; // 北京(深拷贝)
echo "u2: {$u2->address->city}\n"; // 上海
?>
数组的拷贝行为。
```php
// 普通数组是值拷贝
$arr1 = [1, 2, 3];
$arr2 = $arr1;
$arr2[0] = 999;
echo "arr1[0]: {$arr1[0]}\n"; // 1
echo "arr2[0]: {$arr2[0]}\n"; // 999
// 对象数组是浅拷贝
$objArr1 = [new User('张三', new Address('北京'))];
$objArr2 = $objArr1;
$objArr2[0]->name = '李四';
echo "objArr1[0]->name: {$objArr1[0]->name}\n"; // 李四
?>
深拷贝的工具函数。
```php
function deepClone(object $object): object
{
return unserialize(serialize($object));
}
// PHP 7.4+ 可以用 __serialize/__unserialize
$u1 = new User('张三', new Address('北京'));
$u2 = deepClone($u1);
$u2->address->city = '上海';
echo "u1: {$u1->address->city}\n"; // 北京(深拷贝)
echo "u2: {$u2->address->city}\n"; // 上海
?>
理解PHP的对象拷贝机制可以避免意外的引用传递。clone创建浅拷贝,__clone实现深拷贝。序列化/反序列化实现完全深拷贝。在操作嵌套对象时要注意引用关系,避免意外修改。
PHP对象深拷贝与浅拷贝机制