gpt4 book ai didi

symfony - 在 Doctrine Entity Listener 的 preUpdate 中保留其他实体

转载 作者:行者123 更新时间:2023-12-02 02:36:49 33 4
gpt4 key购买 nike

为了清楚起见,我在这里继续讨论开始 here

内部Doctrine Entity Listener ,在 preUpdate 方法中(我可以访问实体任何字段的旧值和新值),我试图保留与焦点无关的实体。

基本上,我有实体 A,当我更改要写入的字段之一中的值时,在 project_notification 表中,字段 oldValue、newValue 以及其他字段。

如果我不在 preUpdate 方法内刷新,新的通知实体不会存储在数据库中。如果我刷新它,我就会进入无限循环。

这是 preUpdate 方法:

public function preUpdate(ProjectTolerances $tolerances, PreUpdateEventArgs $event)
{
if ($event->hasChangedField('riskToleranceFlag')) {
$project = $tolerances->getProject();
$em = $event->getEntityManager();
$notification = new ProjectNotification();
$notification->setValueFrom($event->getOldValue('riskToleranceFlag'));
$notification->setValueTo($event->getNewValue('riskToleranceFlag'));
$notification->setEntity('Entity'); //TODO substitute with the real one
$notification->setField('riskToleranceFlag');
$notification->setProject($project);
$em->persist($notification);


// $em->flush(); // gives infinite loop
}
}

谷歌搜索了一下,我发现你无法在监听器内调用刷新,并且 here建议将要持久保存的内容存储在数组中,以便稍后在 onFlush 中刷新它。尽管如此,它不起作用(并且可能它不应该起作用,因为在调用 preUpdate 后监听器类的实例会被销毁,因此当您稍后调用 onFlush 时,您在类级别作为 protected 属性存储的任何内容都会丢失,或者我错过了什么?)。

这是监听器的更新版本:

class ProjectTolerancesListener
{
protected $toBePersisted = [];

public function preUpdate(ProjectTolerances $tolerances, PreUpdateEventArgs $event)
{
$uow = $event->getEntityManager()->getUnitOfWork();
// $hasChanged = false;

if ($event->hasChangedField('riskToleranceFlag')) {
$project = $tolerances->getProject();
$notification = new ProjectNotification();
$notification->setValueFrom($event->getOldValue('riskToleranceFlag'));
$notification->setValueTo($event->getNewValue('riskToleranceFlag'));
$notification->setEntity('Entity'); //TODO substitute with the real one
$notification->setField('riskToleranceFlag');
$notification->setProject($project);

if(!empty($this->toBePersisted))
{
array_push($toBePersisted, $notification);
}
else
{
$toBePersisted[0] = $notification;
}
}
}

public function postFlush(LifecycleEventArgs $event)
{
if(!empty($this->toBePersisted)) {

$em = $event->getEntityManager();

foreach ($this->toBePersisted as $element) {

$em->persist($element);
}

$this->toBePersisted = [];
$em->flush();
}
}
}

也许我可以通过从监听器内部触发一个事件来解决这个问题,其中包含刷新后执行日志操作所需的所有信息...但是:

1)我不知道我是否能做到

2)这似乎有点矫枉过正

谢谢!

最佳答案

我把所有的功劳都归功于理查德,他为我指明了正确的方向,所以我接受他的回答。尽管如此,我还是为 future 的访问者发布了我的答案以及完整的代码。

class ProjectEntitySubscriber implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(
'onFlush',
);
}

public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();

foreach ($uow->getScheduledEntityUpdates() as $keyEntity => $entity) {
if ($entity instanceof ProjectTolerances) {
foreach ($uow->getEntityChangeSet($entity) as $keyField => $field) {
$notification = new ProjectNotification();
// place here all the setters
$em->persist($notification);
$classMetadata = $em->getClassMetadata('AppBundle\Entity\ProjectNotification');
$uow->computeChangeSet($classMetadata, $notification);
}
}
}
}
}

关于symfony - 在 Doctrine Entity Listener 的 preUpdate 中保留其他实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30734814/

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