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

问题描述 投票:39回答:3

我创建了一个实体AOneToMany关系B,它有OneToManyC的关系。

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

我试过的是将A id设置为null

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

它在A表中创造了新记录,但在BC中没有。

如何制作A实体的完整副本?

doctrine-orm symfony-2.1
3个回答
66
投票

您必须在实体中实现__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;
    }
}

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

根据coder4的评论显示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;
    }
}

9
投票

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

https://github.com/myclabs/DeepCopy

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

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


1
投票

我无法使用DeepClone(它需要php 7.1+),所以我创建了更简单的方法来克隆实体__clone方法中的关系

$this->tags = new ArrayCollection($this->tags->toArray());
© www.soinside.com 2019 - 2024. All rights reserved.