IT story

PHP에서 객체 배열을 복제하는 방법은 무엇입니까?

hot-time 2020. 12. 28. 22:02
반응형

PHP에서 객체 배열을 복제하는 방법은 무엇입니까?


개체 배열이 있습니다. 객체는 "참조"로 할당되고 배열은 "값"으로 할당된다는 것을 알고 있습니다. 그러나 배열을 할당하면 배열의 각 요소가 객체를 참조하므로 두 배열의 객체를 수정하면 변경 사항이 다른 배열에 반영됩니다.

배열을 복제하는 간단한 방법이 있습니까, 아니면 각 개체를 복제하기 위해 반복해야합니까?


동일한 객체에 대한 참조는 배열을 복사 할 때 이미 복사됩니다. 그러나 두 번째 배열을 만들 때 첫 번째 배열에서 참조되는 객체 얕은 복사복사 하려는 것처럼 들리 므로 별개이지만 유사한 객체의 두 배열을 얻습니다.

제가 지금 생각 해낼 수있는 가장 직관적 인 방법은 루프입니다. 더 간단하거나 더 우아한 해결책이있을 수 있습니다.

$new = array();

foreach ($old as $k => $v) {
    $new[$k] = clone $v;
}

$array = array_merge(array(), $myArray);

동일한 개체에 대한 참조를 피하기 위해 개체를 복제해야합니다.

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

AndreKR이 제안한대로 배열에 객체가 포함되어 있다는 것을 이미 알고있는 경우 array_map ()을 사용하는 것이 가장 좋은 방법입니다.

$clone = array_map(function ($object) { return clone $object; }, $array);

나는 또한 클론을 선택했습니다. 배열을 복제하는 것은 일 때문에에 관해서는, (일부 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);

직렬화 및 직렬화 해제를 사용한 어레이 복제

객체가 직렬화를 지원하는 경우 잠자기 상태 및 뒤로 둘러보기를 통해 얕은 얕은 복사 / 복제 를 수행 할 수도 있습니다 .

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

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

$b[0]->store='bar';
var_dump($a, $b);

그러나 그것은 약간 모험적 일 수 있습니다.


당신은 그것을 반복 할 필요가 있습니다 (아마도 array_map()와 같은 함수를 사용하여 ), 배열의 깊은 복사를 자동으로 수행하는 PHP 함수는 없습니다.


다음과 같이했습니다.

function array_clone($array) {
    array_walk_recursive($array, function(&$value) {
        if(is_object($value)) {
            $value = clone $value;
        }
    });
    return $array;
}

arg 함수는 객체를 복제하지 않고 배열을 복사 한 다음 중첩 된 각 객체가 복제됩니다. 따라서 알고리즘이 함수 내에서 사용되지 않으면 작동하지 않습니다.

이 함수는 배열을 재귀 적으로 복제합니다. 이것을 원하지 않는 경우 array_walk대신 사용할 수 있습니다 array_walk_recursive.


다음은 객체 배열 및 복제에 대한 모범 사례입니다. 일반적으로 배열에 사용되는 각 객체 클래스 (또는 인터페이스)에 대해 Collection 클래스를 갖는 것이 좋습니다. 마법 기능을 사용하면 __clone복제가 공식화 된 루틴이됩니다.

class Collection extends ArrayObject
{
     public function __clone()
     {
        foreach ($this as $key => $property) {
            $this[$key] = clone $property;
        }
     }
}

어레이를 복제하려면 컬렉션으로 사용한 다음 복제하십시오.

$arrayObject = new Collection($myArray);
$clonedArrayObject = clone $arrayObject;

한 단계 더 나아가 클래스와 각 하위 클래스에도 clone 메서드를 추가해야합니다. 이는 딥 클로닝에 중요하거나 의도하지 않은 부작용이있을 수 있습니다.

class MyClass
{
     public function __clone()
     {
        $this->propertyContainingObject = clone $this->propertyContainingObject;
     }
}

An important note on using ArrayObject is, that you cannot use is_array() any longer. So be aware of this on refactoring your code.


or also

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

but it is expensive, I prefer Sebastien version (array_map)


Objects are passed by pointed by default and are not always easy to clone especially as they may have circular references. You would be better suited with a different choice of data structures.

For those providing solutions to shallow copy the easier way is this:

 $b = (array)$a;

For deep copies I do not recommend this solution:

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

This is for a deep copy. It only supports a subset of PHP types and will swap objects to array or arrays to objects which might not be what you want as well as potentially corrupting binary values and so on.

If you make a manual recursive function for deep copies the memory usage will be much less afterwards for scalar values and keys so using json or any serializer an impact beyond its point of execution.

It may be better to use unserialize(serialize($a)) for deep copies if performance is not a concern which has wider support for things such as objects though I would not be surprised if it breaks for circular references and several other unusual things.

array_merge_recursive or array_walk_recursive can also be used for arrays.

You can easily create your own recursive function that uses is_object and is_array to choose the appropriate means of copying.


For PHP 5 and above one can use ArrayObject cunstructur to clone an array like the following:

$myArray = array(1, 2, 3);
$clonedArray = new ArrayObject($myArray);

If you have multidimensional array or array composed of both objects and other values you can use this method:

$cloned = Arr::clone($array);

from that library.

ReferenceURL : https://stackoverflow.com/questions/6418903/how-to-clone-an-array-of-objects-in-php

반응형