如何在修改之前获取原始数据?

时间:2018-05-17 15:09:33

标签: symfony symfony-3.3

我有简单的产品实体editAction。它在原始的,标准的方式下工作正常但我需要一些特殊的验证才能在编辑后坚持产品。产品在分离的领域几乎没有价格。在项目中,我对产品进行了一般设置“最低价格”。在我编辑后保存产品之前,我想要将价格与“最低价格”进行比较。我是这样做的:

public function editAction(Request $request, Product $pr1, UserInterface $op)
{
    // 1
    $pr_original = $this->getDoctrine()->getRepository(Product::class)->getProductById($pr1->getId());

    $form = $this->createForm('AppBundle\Form\ProductType', $product);
    $form->handleRequest($request); 

    if($form->isSubmitted() && $form->isValid())
    {
        // 2
        $em = $this->getDoctrine()->getManager();
        $em->persist($product);
        $em->flush();
    }

    return $this->redirect(path('product_list'));
}

在2中我有比较价值的地方。但问题是......我无法获得与之相比的原始值。在1我希望获得原始产品,但它已经$pr_original已经更改了值!这很奇怪,因为我直接在数据库中看到对象仍然具有原始值。所以我认为Symfony不会对数据库进行新的查询。那现在该怎么办?如何让Symfony让我成为原始对象?

2 个答案:

答案 0 :(得分:2)

您需要了解Doctrine为您做的事情。 ORM不是简单的查询创建者。它们将数据库的状态映射到代码理解并能够使用的内存中对象。

因此,当您传递与您一样的表单时,对该对象进行doctrine查询并更新对象状态中的值。因此,在处理表单之后,您的对象已经具有与数据库中的对象不同的状态。理论上唯一要做的就是持久化和刷新,换句话说,注册状态更改将反映在数据库中(持久化)并实际更改数据库值(刷新)。

如果您查询的是"托管" (意思是,已经被查询并且在教义的记忆中)然后,为了效率,教义会给你内存中的对象。它不会再次查询数据库。您可以调用管理器中的refresh method来更新数据库中对象的状态,但这将意味着丢失尚未保留的状态,例如来自表单的数据。

在这种情况下,我建议您创建一个表单事件,将用户使用的值与系统值进行比较。表单事件必须为preSetData,因为您希望在使用新数据更新实体之前进行比较。您可以在here

查看更多内容

另一种方法是创建自定义验证约束。如果您的系统值已修复,则可以使用自定义验证程序对其进行验证。或者甚至是正常的Comparison Constraints

希望此信息有所帮助!

答案 1 :(得分:0)

感谢@Cerad - 您的评论是解决方案:

Doctrine具有所谓的工作单元缓存。每次使用相同的ID进行查询时,您总是会返回完全相同的对象。考虑克隆您的实体:

$prOriginal = clone $pr1;

它对我有用。