Cancel additional Doctrine events for an instance of a given object
To handle some recent critical errors in my application, I set up a Doctrine listener for two events: prePersist
and preRemove
. When an error occurs ...
- ... while the object is saved, it is deleted.
- ... while the object is removed, it is retained.
These actions are done with ...
$args->getEntityManager()->remove($args->getEntity()); $args->getEntityManager()->persist($args->getEntity());
... respectively. However, if an error is detected as prePersist
well as preRemove
, it creates a cycle of events:
- The object is saved:
prePersist
starts. - An
prePersist
error occurs that causesremove()
. - Object deleted:
preRemove
starting. - An
preRemove
error occurs that causespersist()
. - Back to 1.
To avoid this, I would like to cancel any further event handling on my object. In this case: when prePersist
run for the first time, it must somehow mark the object so that it becomes independent of the event chain. If possible, I would like not to add the field to my entity.
Is there any way to implement such a thing? Or maybe I should find another way to undo persistence or deletion in the first place?
source to share
You can modify your code to use an event listener instead of an event listener, and then you can easily track any objects that have errors.
Here's some pseudocode to get the idea:
class EventSubscriber implements EventSubscriber
{
private $hasErrors = [];
public function getSubscribedEvents()
{
return array(
Events::prePersist,
Events::preRemove,
);
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = ...
if ($error) {
if (isset($this->hasErrors[$entity->getId()])) {
return; // don't remove entity
}
$this->hasErrors[$entity->getId()] = true;
$this->getEntityManager()->remove($entity);
}
}
public function preRemove(LifecycleEventArgs $args)
{
$entity = ...
if ($error) {
if (isset($this->hasErrors[$entity->getId()])) {
return; // don't persist entity
}
$this->hasErrors[$entity->getId()] = true;
$this->getEntityManager()->persist($entity);
}
}
}
source to share