如果我进行更改并将表单提交为“重复”,代码将使用我的实体上的$view-> id和其他关联的函数克隆$view对象.这使得教义在数据库中保持记录时能够创造新的记录.这样做完美.欢呼!
但是,对记录所做的更改也保留到已克隆的原始实体(并因此保存到数据库).所以将这些更改保存到两个数据库记录.我碰巧喜欢这个功能,但是我需要明白为什么它在做,所以它不会破坏.以下是相关的代码段:
// File: CmsBundle/Controller/AdminEditController.PHP // Get the Entity Manager $em = $this->getDoctrine()->getManager(); // Get the View based on the requested ID // Is there some magic that happens here to make the entity manager track this $view entity? $view = $em->getRepository("GutensiteCmsBundle:View\View")->find($request->query->get('id')); // VarIoUs bits of code to do whatever I want before a save // ... if ($request->isMethod( 'POST' )) { $form->handleRequest($request); if( $form->isValid() ) { // Duplicate the view entity if the view button is pushed if( $form->has('duplicate') && $form->get('duplicate')->isClicked() ) { $view = clone $view; } // Persist the cloned view $em->persist($view); $em->flush(); } }
View实体有一个特殊的克隆功能,可以在克隆中触发,该克隆重置克隆版本的ids:
// File: CmsBundle/Entity/View.PHP public function __clone() { if($this->id) { $this->setId(null); $this->setLockVersion(1); $this->setPublished(null); // Clone associated entities and reassociate with THIS version (even though there is no id yet,there will be when it persists) // clone the current version (which also has a clone function like this) $version = clone $this->getVersion(); // reset the viewid with a custom function $version->resetView(); // Add this cloned verion to the version history $this->addVersion($version); }
我已经阅读了很多有关克隆的信息,并且一直被告知您不需要detach原始$视图从实体经理.此外,我已经尝试过,没有任何好处.由表单提交并在克隆之前处理为$视图的$view的更改仍保存到原始$视图记录ID(例如33)以及新的克隆记录(例如62).所以两个持续的事情正在发生,即使一个实体只有一个持久化.
到底是怎么回事?
更新
我被告知,如果您使用实体管理器加载实体,则由实体管理器进行跟踪.因此,如果您随时调用flush(),即使您没有在实体上调用persist($view),任何更改都将被持久化.所以当我克隆实体时,实体管理器有效地管理2个实体:原始和克隆.
我尝试在克隆之前从实体管理器中分离出两种视图:
// detach method 1 $em->detach($view); $em->flush(); // detach method 2 $em->refresh($view); $em->flush(); // clone the view after detaching the first entity. $view = clone $view;
但是,实体管理器仍然会将原始$视图记录的修改保留下来.
我也尝试添加unset($this-> _entityPersister,$this-> _identifier)的建议;到我的自定义__clone()方法.但是,也没有将原始实体或克隆的版本从实体管理器分离出来.更改已保存到旧记录和新记录.
没有什么似乎使实体管理器忽略原始实体.
有用的参考
$view1 = new View(); $view1->text = '1'; $em->persist($view1); $em->flush();
现在你有一个记录与文本==’1’存储.
然后:
$view1->text = 'one'; //important! $view2 = new View(); $view2->text = 'two'; $view3 = new View(); $view3->text = 'three'; $em->persist($view2); $em->flush();
调用flush()更新$view1,插入$view2,并忽略您的$view3,因为最后一次不会持续.因此,您有两个记录“一”和“二”.
可以为所选对象调用flush().所以调用$em-> flush($view2)将只插入$view2,而使$view1不变.
在你的简单的例子中,它将工作.
但是请确保$em-> flush()不会再发生.
否则确保您的$view1将保持不变,尝试$em-> refresh($view1)它.