我有一个对象A,它包含一个对象集合B,而这些对象又包含一个对象集合C,它又包含一个对象集合。
我需要从DB中检索对象A,从中创建一个表单,在表单的字段中更改一些值(将来还可以在集合中添加和删除元素)并在DB上保留一个新的对象A适当引用新B,新C和新D。
下面的对象CVC是我的A.
如果我这样做:
$storedCVC = $this->getDoctrine()
->getRepository('AppBundle:CVC')
->find($id);
$clonedCVC = clone $storedCVC;
$form = $this->createForm(new CVCFormType(), $ClonedCVC);
当我转储两个对象时,AI会看到对象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;
}
问题是我创建的对象不同,所以当我尝试在其上调用create表单时它会失败:
任何帮助?
编辑:关系是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?
以下是视觉上的情况:
答案 0 :(得分:2)
您必须在实体中实现__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