如何在PHP中克隆一个对象数组?

69

我有一个对象数组。我知道对象是通过“引用”分配的,而数组是通过“值”分配的。但是当我分配数组时,每个数组元素都引用对象,因此当我在数组中修改对象时,另一个数组中的更改也会反映出来。

是否有简单的方法可以克隆一个数组,或者必须循环遍历每个对象以克隆它们?


2
对象的引用是按值分配的。 - BoltClock
16个回答

1
或者也可以。
$nuarr = json_decode(json_encode($array));

但是它很贵,我更喜欢Sebastien版本(array_map)。

1

默认情况下,对象是通过指针传递的,并且不总是易于克隆,特别是当它们可能具有循环引用时。选择不同的数据结构会更合适。

对于那些提供浅拷贝解决方案的人,最简单的方法是:

 $b = (array)$a;

对于深拷贝,我不建议使用以下解决方案:

$nuarr = json_decode(json_encode($array));

这是用于深拷贝的。它仅支持 PHP 类型的子集,并将对象交换为数组或数组交换为对象,这可能不是您想要的,同时还可能破坏二进制值等。

如果您为深拷贝制作手动递归函数,则标量值和键的内存使用量之后将大大减少,因此使用 json 或任何序列化程序会对其执行点之外产生影响。

如果性能不是问题,则可以使用 unserialize(serialize($a)) 进行深拷贝,它对诸如对象之类的东西具有更广泛的支持,尽管我不会感到惊讶,如果它在循环引用和其他几个不寻常的情况下出现故障。

array_merge_recursive 或 array_walk_recursive 也可用于数组。

您可以轻松创建自己的递归函数,该函数使用 is_object 和 is_array 来选择适当的复制方式。


0
如果您有多维数组或由对象和其他值组成的数组,您可以使用以下方法:
$cloned = Arr::clone($array);

来自那个库


0

我更喜欢使用递归的方式:

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);

1
请不要仅仅发布代码作为答案,还要提供解释您的代码是如何解决问题的。带有解释的答案通常更有帮助和更高质量,并且更有可能吸引赞同。 - bruce szalwinski

0
$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', )

这些数组中的元素是标量值,因此不是对象引用。这并没有回答问题。 - wizulus
如果您的所有标量值都在数组中,或者您想要对象的浅拷贝,那么这是一个绝佳的解决方案。 - Jamshad Ahmad

0

只需在所有类中包含此函数。如果对象本身内部有对象数组,则会对所有对象进行深度克隆。它将触发这些类中的所有__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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接