具有相关实体的深度克隆Doctrine实体

hsz*_*hsz 43 doctrine-orm symfony-2.1

我已经创建了一个实体AOneToMany关系B,这有关系OneToManyC.

我必须克隆此A实体并使用新的id在数据库中设置它.所有深层关系也应该用新的ID来克隆.

我试过的是将Aid 设置为null:

$A = clone $A_original;
$A->setId(null);
$em->persist($A);
Run Code Online (Sandbox Code Playgroud)

它在A表中创建新记录,但不在B和中C.

我该怎么做才能制作完整的A实体副本?

fle*_*lec 68

您必须__clone()在实体中实现一个方法,将id设置为null并根据需要克隆关系.因为如果你保持ID与相关对象它假定你的新的实体A有关系的现有实体BC.

克隆方法A:

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

克隆方法BC:

public function __clone() {
    if ($this->id) {
        $this->setId(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

根据coder4的评论显示OneToMany关系的克隆方法,OneToMany在A哪里$this->M,因此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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有没有特别的理由使用`$ this-> setId(null)`而不是`$ this-> id = null`? (2认同)
  • @PierredeLEESPINAY如果您有一个setter,我建议您使用它,因为其中可能还有一些其他逻辑应该在更改id时触发。除此之外,我认为没有特别的理由使用 setter。对于克隆,它应该具有相同的效果。 (2认同)

Ons*_*hop 10

还有一个模块可以执行此操作,称为DeepCopy:

https://github.com/myclabs/DeepCopy

$deepCopy = new DeepCopy();
$myCopy   = $deepCopy->copy($myObject);
Run Code Online (Sandbox Code Playgroud)

您还可以添加过滤器以自定义复制过程.

  • 我发现了这个令人难以置信的错误,并且它更快地推出您自己的“克隆”方法 (2认同)