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



我对产品实体有简单的编辑操作。它以原始的标准方式工作正常,但我需要在编辑后保留产品之前进行一些特殊验证。产品在单独的字段中价格很少。在项目中,我为产品设置了"最低价格"。在编辑后保存产品之前,我想将价格与"最低价格"进行比较。我是这样做的:

public function editAction(Request $request, Product $pr1, UserInterface $op)
{
// 1
$pr_original = $this->getDoctrine()->getRepository(Product::class)->getProductById($pr1->getId());
$form = $this->createForm('AppBundleFormProductType', $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得到我的原创对象?

你需要了解教义为你做了什么。ORM不是容易查询的创建者。它们将数据库的状态映射到代码理解并能够使用的内存中对象。

因此,当您像以前一样传递表单时,doctrine 会查询对象并更新对象状态中的值。因此,在处理表单后,您的对象已经具有与数据库中的状态不同的状态。留给 doctrine 唯一要做的就是持久和刷新,或者换句话说,注册状态更改将反映在数据库中(持久)并实际更改 db 值(刷新)。

如果你查询一个"托管"的对象(意思是,已经被查询并且已经在 ism 的内存中),那么 doctrine 会给你内存中的对象,为了提高效率。它不会再次查询数据库。您可以在管理器中调用 refresh 方法以从数据库更新对象的状态,但这意味着丢失尚未持久化的状态,例如来自表单的数据。

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

另一种方法是创建自定义验证约束。如果您的系统值是固定的,则可以使用自定义验证程序进行验证。甚至,使用正常的比较约束。

希望这些信息对您有所帮助!

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

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

$prOriginal = clone $pr1;

它对我来说效果很好。

最新更新