2012-04-09 1 views
3

많은 참조를 포함하는 복잡한 PHP 객체의 복제본을 만드는 가장 좋은 방법은 무엇입니까? 그러면 새 객체의 참조가 원래 객체의 참조가 아닌 자체 메서드 및 속성을 가리 키도록 할 수 있습니까?PHP - 자신에 대한 참조가 들어있는 객체를 복제 하시겠습니까?

을 이해하면 $new_object = clone $old_object;은 참조를 그대로 유지하는 얕은 사본을 생성합니다. 아마도 $ new_object의 참조는 이전 객체의 메소드를 가리킬 것입니다.

해당 매뉴얼 페이지에 대한 의견은 $new_object = unserialize(serialize($old_object));이 깊은 복사본을 만드는 방법임을 시사합니다. 유망한 것처럼 들리지만이 접근법이 내 경우에 대해 정확히 무엇인지 의미하지는 않습니다. 참조가 복제본을 가리 키도록 변환되었는지 또는 절대적으로 또는 다른 것으로 만들어 졌는지, 그리고 내가 원하는 것을 수행하면 참조하는 것이 최선의 방법인지 여부는 확실하지 않습니다.

저는이를 위해 확립 된 표준 방법이 있는지 알고 싶습니다.

(참고 : 문제의 객체는 Drupal Views 객체이지만이 객체에 대한 중요한 특징은 거대하고 재귀가되는 많은 참조를 포함한다는 것입니다. . 당신이 전체 트리를 탐색하려고하면)

답변

3

을 간단한 테스트는 무슨 일 발표 할 예정이다 :

$old = new stdClass(); 
$old->foo = 'bar'; 
$old->baz = &$old; 

print_r($old); 

$new = unserialize(serialize($old)); 

$new->foo = 'new'; 

print_r($new); 
print_r($new->baz->foo); 

이 코드는 자기 심판 지금 복제를 가리키는 것을 알 수있다. http://codepad.org/dSnZ5I10

+0

쿨, 고마워, +1. 이것이 일반화되고 표준화 된 접근법인지 아닌지에 대한 아이디어 (예 : 객체가 거대 할 때 성능상의 단점이 있다면? 내 테스트에서 괜찮은 것 같지만 테스트는 매우 기본입니다. – user568458

+1

개체가 커지면 속도가 느려지지만 그럴 수도 있습니다. 나는 당신의 객체가 얼마나 큰지에 달려 있다고 생각합니다. 직렬화 된 버전은 메모리의 절반 이상을 차지합니다 (string()은 얼마나 큰지를 알려줄 것입니다). 그렇지 않다면 실행 시간은 사소한 것이어야합니다. – Cal

+0

굉장합니다. 그래서 메모리는 간단하게 == strlen (serialize ($ object))를 사용합니다 - 그건 내 질문에 답하고 대답합니다. 감사! – user568458

2

다음은 몇 가지 기본적인 테스트 및 결과입니다. 완전한 대답은 아니지만 잘하면 유용합니다. 내 접근 방식이 잘못되면 또한 나를 수정하십시오.

 $view->somedata = "This is the default"; 
     $view->selfreference =& $view->somedata; 

     $new = clone $view; 
     $new2 = unserialize(serialize($view)); 

     $view->somedata = "This is view"; 
     $new->somedata = "This is new"; 
     $new2->somedata = "This is new2"; 

     echo("$view: ".$view->selfreference); 
     echo("$new: ".$new->selfreference); 
     echo("$new2: ".$new2->selfreference); 

결과 : : $ 뷰를 가정 이미 데이터의 자기 참조 많은로드를 포함하는 객체입니다

'$view: This is new' 
'$new: This is new' 
'$new2: This is new2' 

그래서 첫 번째 조사에서, 그것은 clone 포인트와 얕은 클론처럼 보인다 원본에 대한 자체 참조를 사용하고 unserialize(serialize()) 접근 방식은 참조를 유지 관리하고 새 객체를 가리 킵니다.

따라서 unserialize(serialize())이 작동하고 무한 루프 또는 과도한 재귀로 인해 충돌하지 않습니다. 나는 이것이 최고, 표준 및/또는 허용 된 접근 방식인지 여부에 대한 사람들의 생각을 듣고 싶습니다.

관련 문제