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

Dis*_*oat 57 php arrays clone object

我有一个对象数组.我知道对象由"引用"分配,数组由"值"分配.但是当我分配数组时,数组的每个元素都引用了对象,所以当我修改任一数组中的对象时,更改会反映在另一个数组中.

有没有一种简单的方法来克隆一个数组,或者我必须循环它来克隆每个对象?

小智 58

$array = array_merge(array(), $myArray);
Run Code Online (Sandbox Code Playgroud)

  • 这不是克隆数组中的对象(就像它被问到的那样)!所以我不明白这个答案和高投票?它与$ arrB = $ arrA几乎相同,只是数字键正在重新编制索引. (40认同)
  • @GeorgeLund不,这没什么不同.见http://www.php.net/manual/en/function.array-merge.php#92346 (7认同)
  • 在这个解决方案中,我们从$ myArray中丢失了原始数字键:"输入数组中带有数字键的值将使用从结果数组中从零开始的递增键重新编号." (3认同)
  • 那很聪明!比foreach循环更清洁! (2认同)
  • 这实际上与$ array = $ myArray不同吗?请参见http://stackoverflow.com/questions/1532618/is-there-a-function-make-a-copy-of-a-php-array-to-another (2认同)
  • 最聪明的:*仔细阅读问题*,并意识到这个答案并不符合问题的要求 - 这些评论中给出的变化也不符合问题的要求! (2认同)

Bol*_*ock 47

复制数组时,已复制对相同对象的引用.但是,当您创建第二个数组时,听起来您想要对第一个数组中引用的对象进行浅层复制,因此您将获得两个不同但相似的对象数组.

我现在能够提出的最直观的方法是循环; 那里可能有更简单或更优雅的解决方案:

$new = array();

foreach ($old as $k => $v) {
    $new[$k] = clone $v;
}
Run Code Online (Sandbox Code Playgroud)

  • 他现在正在做的是_shallow复制_,他想_deep copy_.你的代码是对的,但你的术语不是. (11认同)
  • @BoltClock:你是否浅层对象取决于特定对象的克隆实现; 这取决于对象的设计者,而不是用户.例如,如果数组中的一个对象包含对另一个对象的引用,并且尚未实现正确的`__clone`函数,那么它仍然只是一个浅拷贝.换句话说:如果您正在克隆的对象的开发人员做得对,那么它将是一个深层拷贝. (2认同)
  • 知道了,我忘记了PHP提供了用于实现深层复制的__clone()方法,并假设默认情况下,浅表复制行为与clone相同。 (2认同)

Dan*_*man 20

您需要克隆对象以避免引用同一对象.

function array_copy($arr) {
    $newArray = array();
    foreach($arr as $key => $value) {
        if(is_array($value)) $newArray[$key] = array_copy($value);
        else if(is_object($value)) $newArray[$key] = clone $value;
        else $newArray[$key] = $value;
    }
    return $newArray;
}
Run Code Online (Sandbox Code Playgroud)


小智 16

正如AndreKR所建议的,如果你已经知道你的数组包含对象,那么使用array_map()是最好的方法:

$clone = array_map(function ($object) { return clone $object; }, $array);
Run Code Online (Sandbox Code Playgroud)


hak*_*kre 5

我也选择了克隆.克隆数组不起作用(你可以考虑一些实施了ArrayAccess为你这样做),因此作为阵列克隆array_map:

class foo {
    public $store;
    public function __construct($store) {$this->store=$store;}
}

$f = new foo('moo');
$a = array($f);

$b = array_map(function($o) {return clone $o;}, $a);

$b[0]->store='bar';    
var_dump($a, $b);
Run Code Online (Sandbox Code Playgroud)

具有序列化和反序列化的数组克隆

如果您的对象支持序列化,您甚至可以通过浏览其睡眠状态和返回来进行深度浅拷贝/克隆:

$f = new foo('moo');
$a = array($f);

$b = unserialize(serialize($a));

$b[0]->store='bar';
var_dump($a, $b);
Run Code Online (Sandbox Code Playgroud)

然而,这可能有点冒险.