web-dev-qa-db-ja.com

ディープクローンDoctrineエンティティと関連するエンティティ

Aとの関係を持つOneToMany関係を持つエンティティBを作成しました。これらの関係はOneToManyCの関係にあります。

このAエンティティのクローンを作成し、新しいIDでデータベースに設定する必要があります。また、すべてのディープリレーションも新しいIDで複製する必要があります。

私が試したのは、A idをnullに設定することです:

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

Aテーブルに新しいレコードを作成しますが、BおよびCには作成しません。

Aエンティティの完全なコピーを作成するにはどうすればよいですか?

41
hsz

エンティティに__clone()メソッドを実装して、IDをnullに設定し、必要に応じてリレーションを複製する必要があります。関連オブジェクトにidを保持する場合、新しいエンティティAが既存のエンティティBおよびCと関係があると想定されるためです。

Aのクローンメソッド:

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

BおよびCのクローンメソッド:

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

Coder4showのコメントに基づいて、A上のOneToMany関係のクローンメソッドを示します。ここで、$this->MはOneToManyであるため、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;
    }
}
66
flec

DeepCopyと呼ばれるこれを行うモジュールもあります。

https://github.com/myclabs/DeepCopy

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

フィルターを追加して、コピープロセスをカスタマイズすることもできます。

9
Onshop

DeepCloneを使用できなかったため(php 7.1以降が必要です)、エンティティ__cloneメソッドでリレーションを複製するより簡単な方法を見つけました。

$this->tags = new ArrayCollection($this->tags->toArray());
1
Andrew Zhilin

Php cloneキーワードを使用するだけで完了です!

$newEntity = clone $oldEntity;

$em = $this->getDoctrine()->getManager();
$em->persist($newEntity);
$em->flush();
0
sadiq