【问题标题】:Symfony2 Cloning entities with collections and entity field typeSymfony2 使用集合和实体字段类型克隆实体
【发布时间】:2015-03-30 13:19:50
【问题描述】:

我的对象 A 包含对象 B 的集合,而 B 又包含对象 C 的集合,而 C 又包含对象 D 的集合。

我需要从 DB 中检索对象 A,从中创建一个表单,更改表单字段中的一些值(将来还会从集合中添加和删除元素)并在 DB 上保留一个包含所有适当引用新 B、新 C 和新 D。

下面的对象CVC是我的A。

如果我这样做:

    $storedCVC = $this->getDoctrine()
                      ->getRepository('AppBundle:CVC')
                      ->find($id);

    $clonedCVC = clone $storedCVC;
    $form = $this->createForm(new CVCFormType(), $ClonedCVC);

当我转储两个对象 A 时,我看到对象 A 的引用不同,但是当我挖掘到对象 C、B 和 D 级别时,引用与原始引用相同(我们可能期望从“浅”克隆,请参见下面的屏幕截图)。

尽管如此,它正确地创建了新对象 A,并且(令人惊讶的是)它还保留了新对象 B、C 和 D(可能是因为我在每个父子关系上指定了以下持久性):

/**
 * @ORM\ManyToOne(targetEntity="CVC", cascade={"persist"}, inversedBy="BenefitItems")
 */
protected $CVC; 

请注意,BenefitItems 是我的对象 B。当然在对象 A 中我有:

/**
 * @ORM\oneToMany(targetEntity="BenefitItem", mappedBy="CVC")
 */    
protected $BenefitItems;

到目前为止一切顺利(尽管对我来说很神秘)。当我尝试映射属于对象 C 的实体类型字段(典型的“类别”字段)时,就会出现问题。当我在表单上更新该实体时,它也会更新原始类别。

我尝试了以下方法来执行深度克隆:

function cloneCVC ($oldCVC) {
$newCVC = new CVC();
foreach ($oldCVC->getBenefitItems() as $oldBI)
    {
    $newBI = new BenefitItem();
    foreach ($oldBI->getBenefitGroups() as $oldBG)
        {
        $newBG = new BenefitGroup();
        foreach ($oldBG->getBenefitSubItems() as $oldSI)
            {
            $newSI = new BenefitSubItem();
            $newSI->setComment($oldSI->getComment());
            $newBG->addBenefitSubItem($newSI);
            }
        $newBG->setBenefitGroupCategory($oldBG->getBenefitGroupCategory());
        $newBI->addBenefitGroup($newBG);
        }
    $newBI->setComment($oldBI->getComment());

    $newCVC->addBenefitItem($newBI);
    }
return $newCVC;
}

问题是我创建的对象不同,所以当我尝试在其上调用创建表单时失败:

有什么帮助吗?

编辑:关系是 A->B->C->D,所以我认为 Stepan 存在误解。然后我们有 C->E 是实体类型字段的关系。

在我的代码中:

A = CVC
B = BenefitItem
C = BenefitGroup
D = BenefitSubItem
E = BenefitGroupCategory

下面建议的代码在 CVC 中正常工作(我现在确实对 BenefitItems 数组有不同的引用,请参见下面的红线)但即使我在 CVC 中执行以下操作:

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

福利项目的克隆不会发生(见黄色和浅蓝色线)。福利项目实体内的代码是:

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

但它永远不会进入 if。我变了

$this->id = null

$this->idXXX = null

导致错误但不会被调用)。

我应该简单地消除 if 吗?

这是视觉上的情况:

【问题讨论】:

    标签: symfony clone symfony-forms


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2015-02-10
      • 2012-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 2014-06-22
      • 2012-07-09
      • 1970-01-01
      相关资源
      最近更新 更多