我有一个对象数组。我知道对象是通过“引用”分配的,而数组是通过“值”分配的。但是当我分配数组时,每个数组元素都引用对象,因此当我在数组中修改对象时,另一个数组中的更改也会反映出来。
是否有简单的方法可以克隆一个数组,或者必须循环遍历每个对象以克隆它们?
$nuarr = json_decode(json_encode($array));
默认情况下,对象是通过指针传递的,并且不总是易于克隆,特别是当它们可能具有循环引用时。选择不同的数据结构会更合适。
对于那些提供浅拷贝解决方案的人,最简单的方法是:
$b = (array)$a;
对于深拷贝,我不建议使用以下解决方案:
$nuarr = json_decode(json_encode($array));
这是用于深拷贝的。它仅支持 PHP 类型的子集,并将对象交换为数组或数组交换为对象,这可能不是您想要的,同时还可能破坏二进制值等。
如果您为深拷贝制作手动递归函数,则标量值和键的内存使用量之后将大大减少,因此使用 json 或任何序列化程序会对其执行点之外产生影响。
如果性能不是问题,则可以使用 unserialize(serialize($a)) 进行深拷贝,它对诸如对象之类的东西具有更广泛的支持,尽管我不会感到惊讶,如果它在循环引用和其他几个不寻常的情况下出现故障。
array_merge_recursive 或 array_walk_recursive 也可用于数组。
您可以轻松创建自己的递归函数,该函数使用 is_object 和 is_array 来选择适当的复制方式。
我更喜欢使用递归的方式:
function deepClone(mixed $object): mixed
{
switch (gettype($object)) {
case 'object':
return clone $object;
case 'array':
$ret = [];
foreach ($object as $key => $item) {
$ret[$key] = deepClone($item);
}
return $ret;
default:
return $object;
}
}
deepClone($array);
$a = ['a'=>'A','b'=>'B','c'=>'C'];
$b = $a+[];
$a['a'] = 'AA'; // modifying array $a
var_export($a);
var_export($b);
结果:
array ( 'a' => 'AA', 'b' => 'B', 'c' => 'C', )
array ( 'a' => 'A', 'b' => 'B', 'c' => 'C', )
只需在所有类中包含此函数。如果对象本身内部有对象数组,则会对所有对象进行深度克隆。它将触发这些类中的所有__clone()
函数:
/**
* Clone the object and its properties
*/
public function __clone()
{
foreach ($this as $key => $property)
{
if(is_array($property))
{
foreach ($property as $i => $o)
{
if(is_object($o)) $this->$key[$i] = clone $o;
else $this->$key[$i] = $o;
}
}
else if(is_object($property)) $this->$key = clone $property;
else $this->$key = $property;
}
}