php – 在Symfony2中克隆一个实体,通过Doctrine保存对原始记录和克隆记录的更改

前端之家收集整理的这篇文章主要介绍了php – 在Symfony2中克隆一个实体,通过Doctrine保存对原始记录和克隆记录的更改前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个表单允许我保存一个记录或重复它.该表格将该记录保存为$view实体,该实体恰好具有多个关联实体,例如. $viewVersion由窗体构建器以具有嵌套实体的formType(这可能是不相关的))管理.

如果我进行更改并将表单提交为“重复”,代码将使用我的实体上的$view-> id和其他关联的函数克隆$view对象.这使得教义在数据库中保持记录时能够创造新的记录.这样做完美.欢呼!

但是,对记录所做的更改也保留到已克隆的原始实体(并因此保存到数据库).所以将这些更改保存到两个数据库记录.我碰巧喜欢这个功能,但是我需要明白为什么它在做,所以它不会破坏.以下是相关的代码段:

  1. // File: CmsBundle/Controller/AdminEditController.PHP
  2.  
  3. // Get the Entity Manager
  4. $em = $this->getDoctrine()->getManager();
  5.  
  6. // Get the View based on the requested ID
  7. // Is there some magic that happens here to make the entity manager track this $view entity?
  8. $view = $em->getRepository("GutensiteCmsBundle:View\View")->find($request->query->get('id'));
  9.  
  10. // VarIoUs bits of code to do whatever I want before a save
  11. // ...
  12.  
  13. if ($request->isMethod( 'POST' )) {
  14. $form->handleRequest($request);
  15. if( $form->isValid() ) {
  16. // Duplicate the view entity if the view button is pushed
  17. if(
  18. $form->has('duplicate')
  19. && $form->get('duplicate')->isClicked()
  20. ) {
  21. $view = clone $view;
  22. }
  23.  
  24. // Persist the cloned view
  25. $em->persist($view);
  26. $em->flush();
  27. }
  28. }

View实体有一个特殊的克隆功能,可以在克隆中触发,该克隆重置克隆版本的ids:

  1. // File: CmsBundle/Entity/View.PHP
  2.  
  3. public function __clone() {
  4. if($this->id) {
  5. $this->setId(null);
  6. $this->setLockVersion(1);
  7. $this->setPublished(null);
  8.  
  9. // Clone associated entities and reassociate with THIS version (even though there is no id yet,there will be when it persists)
  10. // clone the current version (which also has a clone function like this)
  11. $version = clone $this->getVersion();
  12. // reset the viewid with a custom function
  13. $version->resetView();
  14. // Add this cloned verion to the version history
  15. $this->addVersion($version);
  16. }

我已经阅读了很多有关克隆的信息,并且一直被告知您不需要detach原始$视图从实体经理.此外,我已经尝试过,没有任何好处.由表单提交并在克隆之前处理为$视图的$view的更改仍保存到原始$视图记录ID(例如33)以及新的克隆记录(例如62).所以两个持续的事情正在发生,即使一个实体只有一个持久化.

到底是怎么回事?

更新

我被告知,如果您使用实体管理器加载实体,则由实体管理器进行跟踪.因此,如果您随时调用flush(),即使您没有在实体上调用persist($view),任何更改都将被持久化.所以当我克隆实体时,实体管理器有效地管理2个实体:原始和克隆.

我尝试在克隆之前从实体管理器中分离出两种视图:

  1. // detach method 1
  2. $em->detach($view);
  3. $em->flush();
  4.  
  5. // detach method 2
  6. $em->refresh($view);
  7. $em->flush();
  8.  
  9. // clone the view after detaching the first entity.
  10. $view = clone $view;

但是,实体管理器仍然会将原始$视图记录的修改保留下来.

我也尝试添加unset($this-> _entityPersister,$this-> _identifier)的建议;到我的自定义__clone()方法.但是,也没有将原始实体或克隆的版本从实体管理器分离出来.更改已保存到旧记录和新记录.

没有什么似乎使实体管理器忽略原始实体.

有用的参考

> How Clone Works
> Implement Your Own Clone
> Clone Nested

只有当您将实体连接到实体管理器时,才需要Persist.但在你的情况下,原来的“$view record id(例如33)”已经在它内.所以基本上会发生什么:
  1. $view1 = new View();
  2. $view1->text = '1';
  3. $em->persist($view1);
  4. $em->flush();

现在你有一个记录与文本==’1’存储.
然后:

  1. $view1->text = 'one'; //important!
  2.  
  3. $view2 = new View();
  4. $view2->text = 'two';
  5.  
  6. $view3 = new View();
  7. $view3->text = 'three';
  8.  
  9. $em->persist($view2);
  10. $em->flush();

调用flush()更新$view1,插入$view2,并忽略您的$view3,因为最后一次不会持续.因此,您有两个记录“一”和“二”.

可以为所选对象调用flush().所以调用$em-> flush($view2)将只插入$view2,而使$view1不变.

在你的简单的例子中,它将工作.

但是请确保$em-> flush()不会再发生.

否则确保您的$view1将保持不变,尝试$em-> refresh($view1)它.

猜你在找的PHP相关文章