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

时间:2013-01-04 13:29:20

标签: doctrine-orm symfony-2.1

我创建了一个A实体OneToManyB的关系,OneToManyC有关系。

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

我尝试过将A ID设置为null

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

它会在A表中创建新记录,但不在BC中。

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

3 个答案:

答案 0 :(得分:64)

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

答案 1 :(得分:8)

还有一个名为DeepCopy的模块:

https://github.com/myclabs/DeepCopy

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

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

答案 2 :(得分:0)

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

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