gpt4 book ai didi

php - 在 Symfony2 中克隆实体在通过 Doctrine 持久保存时会保存对原始记录和克隆记录的更改

转载 作者:行者123 更新时间:2023-12-02 22:40:17 24 4
gpt4 key购买 nike

我有一个表单,可以让我保存或复制记录。该表单将记录保存为 $view 实体,该实体恰好有多个关联实体,例如$viewVersion 由表单构建器在具有嵌套实体的 formType 中管理(这可能是不相关的)。

如果我进行更改并将表单提交为“复制”,则代码将使用实体上的函数克隆 $view 对象,该函数会取消设置 $view->id 和其他协会。这会迫使 Doctrine 在将记录保存到数据库时创建新记录。这非常有效。万岁!

但是,对记录所做的更改也会保留到克隆的原始实体(并因此保存到数据库)。因此它将这些更改保存到两个数据库记录中。我碰巧喜欢这个功能,但我需要了解它为什么这样做,这样以后就不会中断。以下是相关代码的摘要:

// 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 实体有一个特殊的克隆函数,可以在克隆时触发,从而重置克隆版本的 ID:

// 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 。另外,我也尝试过,但并没有什么效果。对 $view 的更改(在克隆之前由表单提交并处理到 $view)仍然保存到原始 $view 记录 ID(例如 33)以及新的记录 ID 中。克隆记录(例如 62)。因此,尽管在单个实体上只调用了一个持久化,但还是发生了两个持久化。

这是怎么回事?

更新

有人告诉我,如果您使用实体管理器加载实体,实体管理器就会跟踪它。因此,如果您在任何时候调用 flush(),任何更改都将被持久化,即使您没有对实体调用 persist($view) 也是如此。因此,当我克隆实体时,实体管理器有效地管理 2 个实体:原始实体和克隆实体。

我尝试通过两种方式在克隆之前将 View 与实体管理器分离:

// 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;

但是实体管理器仍然保留对原始 $view 记录的更改。

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

似乎没有什么能让实体管理器忽略原始实体。

有用的引用

最佳答案

仅当您将某些内容附加到 Entity Manager 时才需要

Persist 。但在你的情况下,原始的“$view record id (e.g. 33)”已经在其中了。基本上,会发生什么:

$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) 它。

关于php - 在 Symfony2 中克隆实体在通过 Doctrine 持久保存时会保存对原始记录和克隆记录的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24708733/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com