Symfony 教义怪异的行为,改变了我从未坚持过的实体
我有这样的情况: Symfony 4.4.8,在控制器中,对于某些用户,我在显示实体之前更改了实体的某些属性:Symfony 教义怪异的行为,改变了我从未坚持过的实体,symfony,doctrine,symfony4,Symfony,Doctrine,Symfony4,我有这样的情况: Symfony 4.4.8,在控制器中,对于某些用户,我在显示实体之前更改了实体的某些属性: public function viewAction(string $id) { $em = $this->getDoctrine()->getManager(); /** @var $offer Offer */ $offer = $em->getRepository(Offer::class)->find($id); //
public function viewAction(string $id)
{
$em = $this->getDoctrine()->getManager();
/** @var $offer Offer */
$offer = $em->getRepository(Offer::class)->find($id);
// For this user the payout is different, set the new payout
// (For displaying purposes only, not intended to be stored in the db)
$offer->setPayout($newPayout);
return $this->render('offers/view.html.twig', ['offer' => $offer]);
}
然后,我有一个onKernelTerminate侦听器,如果用户语言发生更改,它会更新用户语言:
public function onKernelTerminate(TerminateEvent $event)
{
$request = $event->getRequest();
if ($request->isXmlHttpRequest()) {
// Don't do this for ajax requests
return;
}
if (is_object($this->user)) {
// Check if language has changed. If so, persist the change for the next login
if ($this->user->getLang() && ($this->user->getLang() != $request->getLocale())) {
$this->user->setLang($request->getLocale());
$this->em->persist($this->user);
$this->em->flush();
}
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::TERMINATE => [['onKernelTerminate', 15]],
];
}
现在,这里发生了一件非常奇怪的事情,如果用户改变了语言,即使我从未坚持过,出价也会随着新的支付被刷新到db中
知道如何修复或调试此问题吗
PS:即使我删除
$this->em->persist($this->user),也会发生这种情况代码>,我想可能是因为用户和报价之间的某种关系。。。但事实并非如此
我确信这个提议是持久的,因为我添加了一个dd('beforeUpdate')代码>在Offer::beforeUpdate()方法中,它将打印在页面底部。好的,因此,根据设计,当您在实体管理器上调用flush
时,条令会将对托管实体所做的所有更改提交到数据库
在表示数据库中记录的实体(“托管实体”)上更改“仅用于显示”的值在这种情况下是非常糟糕的设计。这也引出了一个问题:实体上的值实际上意味着什么
根据您的用例,我看到了几个选项:
- 仅为渲染创建显示对象/数组/“dto”:
$display = [
'payout' => $offer->getPayout(),
// ...
];
$display['payout'] = $newPayout;
return $this->render('offers/view.html.twig', ['offer' => $display]);
或者创建一个新的非持久化实体
- 使用覆盖样式渲染逻辑
return $this->render('offers/view.html.twig', [
'offer' => $offer,
'override' => ['payout' => $newPayout],
]);
在模板中,选择替代(如果存在)
{{ override.payout ?? offer.payout }}
- 在实体中添加一个虚拟的字段(意味着它不存储在列中!),可能称之为“displayPayout”,如果它存在,则使用该字段的内容
{{ override.payout ?? offer.payout }}
好的,所以根据设计,当您在实体管理器上调用flush
时,条令将把对托管实体所做的所有更改提交到数据库中
在表示数据库中记录的实体(“托管实体”)上更改“仅用于显示”的值在这种情况下是非常糟糕的设计。这也引出了一个问题:实体上的值实际上意味着什么
根据您的用例,我看到了几个选项:
- 仅为渲染创建显示对象/数组/“dto”:
$display = [
'payout' => $offer->getPayout(),
// ...
];
$display['payout'] = $newPayout;
return $this->render('offers/view.html.twig', ['offer' => $display]);
或者创建一个新的非持久化实体
- 使用覆盖样式渲染逻辑
return $this->render('offers/view.html.twig', [
'offer' => $offer,
'override' => ['payout' => $newPayout],
]);
在模板中,选择替代(如果存在)
{{ override.payout ?? offer.payout }}
- 在实体中添加一个虚拟的字段(意味着它不存储在列中!),可能称之为“displayPayout”,如果它存在,则使用该字段的内容
{{ override.payout ?? offer.payout }}
如果您从Doctrine中的数据库中检索某个内容并对其进行更改,则不需要调用persist,它会自动完成。所以这就是为什么如果你删除持久线,它不会有任何区别。我会重新考虑你的设计。我不会更改实体中的某些内容,除非我计划将其持久化到数据库中。可能使用某种转换器在页面上显示数据库中的数据。刷新意味着您要进行更新。persist用于对数据库的初始写入我确信需要persist来“提交”对数据库的更改。。。从几年前我学习教义开始。。。我一直都错了,你需要persist让一个非托管实体将其标记为托管,所以你需要在某个时刻持久化一个实体,但托管实体不需要persist;o) 如果您从Doctrine中的数据库中检索某个内容并对其进行更改,则不需要调用persist,它会自动完成。所以这就是为什么如果你删除持久线,它不会有任何区别。我会重新考虑你的设计。我不会更改实体中的某些内容,除非我计划将其持久化到数据库中。可能使用某种转换器在页面上显示数据库中的数据。刷新意味着您要进行更新。persist用于对数据库的初始写入我确信需要persist来“提交”对数据库的更改。。。从几年前我学习教义开始。。。我一直都错了,你需要persist让一个非托管实体将其标记为托管,所以你需要在某个时刻持久化一个实体,但托管实体不需要persist;o) 我肯定会用DTO。我肯定会用DTO。