source

PHP에서 객체 배열을 복제하는 방법은?

nicesource 2023. 9. 6. 22:08
반응형

PHP에서 객체 배열을 복제하는 방법은?

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

어레이를 복제하는 간단한 방법이 있습니까? 아니면 각 개체를 복제하려면 이를 루프로 통과해야 합니까?

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

배열을 복사하면 동일한 개체에 대한 참조가 이미 복사됩니다.하지만 당신은 당신이 원하는 것처럼 들립니다. 천박한 두 번째 배열을 만들 때 첫 번째 배열에서 참조되는 개체를 심층 복사하면 서로 다르지만 유사한 개체의 배열을 두 개 얻을 수 있습니다.

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

$new = array();

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

개체를 복제해야 동일한 개체에 대한 참조가 발생하지 않습니다.

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

저도 클론을 선택했습니다.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);

직렬화 및 비직렬화를 사용한 어레이 클론

개체가 직렬화를 지원하는 경우에는 sleep 상태로 이동한 후 다음과 같이 심층 복사/클론을 수행할 수도 있습니다.

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

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

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

하지만, 그것은 약간 모험적일 수 있습니다.

순수 PHP 7.4 >= 솔루션:

$cloned = array_map(fn ($o) => clone $o, $original);

해야 를 합니다 과 합니다 를 를 해야 과 등의 함수를 사용하여 루프array_map()이 경우) 배열의 딥 카피를 자동으로 수행하는 PHP 기능은 없습니다.

저는 이렇게 해왔습니다.

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

function arg는 개체를 복제하지 않고 어레이를 복사한 다음 중첩된 각 개체를 복제합니다.따라서 알고리즘을 함수 내부에서 사용하지 않으면 작동하지 않습니다.

이 함수는 배열을 재귀적으로 복제합니다.능을 사용할 수 .array_walk에 대신에array_walk_recursive이런 일이 일어나지 않기를 바란다면요

여기에 여러 개체와 복제에 대한 저의 모범 사례가 있습니다.일반적으로 각 클래스의 객체(또는 인터페이스)에 대한 Collection 클래스를 갖는 것이 좋습니다. 이 클래스는 배열에 사용됩니다. 기능으로__clone클로닝은 공식화된 루틴이 됩니다.

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

어레이를 복제하려면 Collection(수집)으로 사용한 다음 복제합니다.

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

한 단계 더 나아가 클래스와 각 하위 클래스에도 클론 메서드를 추가해야 합니다.이는 심층 클로닝에 중요하며, 그렇지 않으면 의도하지 않은 부작용이 발생할 수 있습니다.

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

할 때 한 점은 ArrayObject를 사용할 수 is_array() 주의해야 .코드 리팩터링 시 주의하시기 바랍니다.

아니면

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

하지만 비싸요, 저는 세바스티앙 버전(array_map)을 선호합니다.

개체는 기본적으로 가리키는 방향으로 전달되며 특히 원형 참조를 가질 수 있기 때문에 복제가 항상 쉽지는 않습니다.다양한 데이터 구조를 선택하는 것이 더 적합할 것입니다.

얕은 복사를 위한 솔루션을 제공하는 사용자에게 더 쉬운 방법은 다음과 같습니다.

 $b = (array)$a;

심층 복사의 경우 이 솔루션을 권장하지 않습니다.

$nuar = json_parray(json_parray));

이것은 깊은 사본을 위한 것입니다.PHP 유형의 하위 집합만 지원하며 개체를 배열 또는 배열로 전환하여 이진 값을 손상시킬 수도 있습니다.

딥 복사본에 대한 수동 재귀 함수를 만들면 스칼라 값과 키에 대한 메모리 사용량이 이후 훨씬 적으므로 json이나 직렬화기를 사용하면 실행 지점 이상의 영향을 받을 수 있습니다.

성능이 개체와 같은 것에 더 광범위하게 지원되는 문제가 아닌 경우 심층 복사본에 대해 unserialize($a)를 사용하는 것이 더 나을 수 있습니다. 원형 참조 및 기타 특이한 것에 대해 깨져도 놀라지 않을 것입니다.

array_match_match 또는 array_walk_match를 배열에 사용할 수도 있습니다.

is_object와 is_array를 사용하여 적절한 복사 수단을 선택하는 자신만의 재귀 함수를 쉽게 만들 수 있습니다.

5은 PHP 5 의 할 을 사용할 수 있습니다.ArrayObject다음과 같은 배열을 복제하려면 cunstructur를 사용합니다.

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

객체와 다른 값으로 구성다차원 배열 또는 배열이 있는 경우 이 방법을 사용할 수 있습니다.

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

그 도서관에서.

이 기능을 모든 수업에 포함시키기만 하면 됩니다.개체 자체 내에 개체 배열이 있는 경우 모든 개체의 심층 복제가 수행됩니다.든을할다l다은을 트리거합니다.__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;
    }
}
$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', )

나는 재귀적 방법을 선호합니다.

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

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

반응형