Zur Klarheit fahre ich hier fort die Diskussion begann here.Persistent andere Entitäten in PreUpdate von Doctrine Entity Listener
In einem Doctrine Entity Listener, in der preUpdate-Methode (wo ich auf den alten und neuen Wert eines Feldes der Entität zugreifen kann) versuche ich eine Entität persistent zu sein, die nicht mit der fokalen Einheit verwandt ist.
Grundsätzlich habe ich Entität A, und wenn ich einen Wert in einem der Felder, die ich schreiben möchte, in der Projektnotifikationstabelle die Felder oldValue, newValue und andere ändern.
Wenn ich die preUpdate-Methode nicht lösche, wird die neue Benachrichtigungsentität nicht in der DB gespeichert. Wenn ich es spüle, gehe ich in eine Endlosschleife.
Dies ist die Preupdate Methode:
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
}
}
ein bisschen Googeln ich entdeckte, dass Sie nicht die Spülung in den Hörer anrufen können, und here ist es vorgeschlagen, das Zeug zu speichern in einem Array beibehalten werden, es zu spülen später im onFlush. Nichtsdestoweniger funktioniert es nicht (und wahrscheinlich sollte es nicht funktionieren, da die Instanz der Listener-Klasse nach dem Aufruf des preUpdate zerstört wird. Also geht alles, was Sie als geschütztes Attribut auf der Ebene der Klasse speichern, verloren, wenn Sie später onFlush aufrufen oder fehle ich etwas?). Hier
ist die aktualisierte Version des Zuhörers:
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();
}
}
}
Vielleicht kann ich dieses Problem lösen, indem sie ein Ereignis aus dem Inneren des Zuhörers mit allen benötigten Informationen Brennen meiner Holzeinschlag nach dem Flush durchführen ... aber :
1) ich weiß nicht, ob ich es
2) tun kann, scheint es ein wenig zuviel des Guten
Thank you!
Haben Sie im onFlush Zugriff auf oldValue und newValue? –
Sicher tun. UnitOfWork hat dafür getEntityChangeSet - http://www.doctrine-project.org/api/orm/2.0/class-Doctrine.ORM.UnitOfWork.html – Richard