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

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

如果我进行更改并将表单提交为“重复”,代码将使用我的实体上的$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()方法.但是,也没有将原始实体或克隆的版本从实体管理器分离出来.更改已保存到旧记录和新记录.

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

有用的参考

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

只有当您将实体连接到实体管理器时,才需要Persist.但在你的情况下,原来的“$view record id(例如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相关文章