Description
Symfony version(s) affected
6.2
Description
It seems that it it not possible to disable the listener using EventManager
. For particular case I want to disable SoftDeleteableListener
from gedmo library. It is registered in the container as gedmo.listener.softdeleteable
service (see steps to reproduce).
In order to disable it, I inject this listener into the custom service and call removeEventSubscriber()
. It turns out to be that listener is still present in EventManager
and executes onFlush()
.
Would be nice to fix the ability to disable event listeners, since doctrine supports it.
How to reproduce
Register listener:
gedmo.listener.softdeleteable:
class: Gedmo\SoftDeleteable\SoftDeleteableListener
tags:
- { name: doctrine.event_listener, event: 'onFlush' }
- { name: doctrine.event_listener, event: 'loadClassMetadata' }
calls:
- [ setAnnotationReader, [ "@annotation_reader" ] ]
Create service to disable softdeleteable:
final class ConditionalSoftDelete
{
private SoftDeleteableListener $listener;
#[Required]
public function setListener(SoftDeleteableListener $softDeleteableListener): void
{
$this->listener = $softDeleteableListener;
}
public function disableListener(EntityManagerInterface $entityManager)
{
$entityManager
->getEventManager()
->removeEventSubscriber($this->listener);
}
}
In the client code call $conditionalSoftDelete->disableListener()
.
After that try to remove entity having soft deleteable attribute via entity manager: $em->remove($entity);
See in the database that entity was never removed, but was updated (deletedAt field was populated).
Possible Solution
No response
Additional Context
Debugging showed that removeEventSubscriber()
doesn't work, since ContainerAwareEventManager::getHash()
method returns spl_object_hash
of the object, while listener was registered with string:
private function getHash(string|object $listener): string
{
if (\is_string($listener)) {
return '_service_'.$listener; // listener registered with this has
}
return spl_object_hash($listener); // we are trying to disable by this hash
}
Therefore, it disables nothing, and we still have listener enabled.
As you can see on the screenshot, hash key is _service_gedmo.listener.softdeleteable
, while real hash (object) is 00000000000003450000000000000000
.