2013-01-04 18 views
31

Tôi đã tạo một thực thể A với OneToMany liên quan đến B, có quan hệ OneToMany đến C.Bản sao sâu Thực thể Doctrine với các thực thể liên quan

Tôi phải sao chép thực thể A này và đặt nó trong cơ sở dữ liệu với id mới. Ngoài ra tất cả các mối quan hệ sâu sắc nên được nhân bản với id mới quá.

có gì tôi đã cố gắng là để thiết lập A id để null:

$A = clone $A_original; 
$A->setId(null); 
$em->persist($A); 

Nó tạo ra kỷ lục mới trong A bảng, nhưng không ở BC.

Tôi nên làm gì để tạo bản sao đầy đủ của thực thể A?

Trả lời

47

Bạn phải triển khai phương thức __clone() trong đối tượng đặt id thành rỗng và nhân bản quan hệ nếu muốn. Bởi vì nếu bạn giữ id trong đối tượng liên quan, nó giả định rằng thực thể mới của bạn A có liên quan đến các thực thể hiện có BC.

Clone-phương pháp cho A:

public function __clone() { 
    if ($this->id) { 
     $this->setId(null); 
     $this->B = clone $this->B; 
     $this->C = clone $this->C; 
    } 
} 

Clone-phương pháp cho BC:

public function __clone() { 
    if ($this->id) { 
     $this->setId(null); 
    } 
} 

https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/Nu2rayrDkgQ

https://doctrine-orm.readthedocs.org/en/latest/cookbook/implementing-wakeup-or-clone.html

Dựa trên những nhận xét của coder4 hiển thị một bản sao-phương pháp cho một mối quan hệ OneToMany trên A nơi $this->M là OneToMany và do đó một ArrayCollection:

public function __clone() { 
    if ($this->id) { 
     $this->setId(null); 

     // cloning the relation M which is a OneToMany 
     $mClone = new ArrayCollection(); 
     foreach ($this->M as $item) { 
      $itemClone = clone $item; 
      $itemClone->setA($this); 
      $mClone->add($itemClone); 
     } 
     $this->M = $mClone; 
    } 
} 
+0

Vấn đề duy nhất với điều này là, nó không có vẻ làm việc trên OneToMany, bất kỳ ý tưởng nào tại sao? – coder4show

+1

@ coder4show đó là bởi vì bạn đang nhân bản các 'ArrayCollection' và không phải là các yếu tố trong đó. Tôi đã thêm một phương pháp nhân bản cho mối quan hệ OneToMany. – flec

+0

Trong ví dụ này mối quan hệ OneToMany sẽ không được nhân bản một cách chính xác, vì các thực thể liên quan nhân bản vô tính vẫn tham chiếu đến thực thể cũ. Xem [câu trả lời này] (http://stackoverflow.com/a/28313673/3215645) để có ví dụ làm việc – Richard

6

Ngoài ra còn có một mô-đun sẽ làm gọi DeepCopy này:

https://github.com/myclabs/DeepCopy

$deepCopy = new DeepCopy(); 
$myCopy = $deepCopy->copy($myObject); 

Bạn cũng có thể thêm bộ lọc để tùy chỉnh quá trình sao chép.

+0

Xin chào @Ben bạn có thể xem [this] (http://stackoverflow.com/questions/28650001/clone-entity-in-cascade-mode?noredirect=1#comment45641837_28650001) – ReynierPM

+1

Tôi đã tìm thấy điều này cực kỳ lỗi và nhanh hơn để cuộn các phương thức 'clone' của riêng bạn –

0

Tôi wasnt thể sử dụng DeepClone (nó đòi hỏi php 7.1+), vì vậy tôi thành lập cách đơn giản hơn để sao chép các mối quan hệ trong phương pháp __clone thực thể

$this->tags = new ArrayCollection($this->tags->toArray()); 
Các vấn đề liên quan