问题
I am trying to inject one of my services into an EntityListener
in order to call some application specific behaviour when an entity gets updated.
My Logger
service, used to store events in a LogEntry
entity in my database:
class Logger
{
/**
* @var EntityManager $manager The doctrine2 manager
*/
protected $manager;
//...
}
The listener:
class EntityListener
{
public function __construct(Logger $logger)
{
$this->logger = $logger;
// ...
}
}
And the service definitions in my service.yml
:
listener:
class: Namespace\EntityListener
arguments: [@logger]
tags:
- { name: doctrine.event_listener, event: preUpdate }
logger:
class: Namespace\Logger
arguments: [@doctrine.orm.entity_manager]
Unfortunately it results in a ServiceCircularReferenceException
:
Circular reference detected for service "doctrine.orm.default_entity_manager", path: "doctrine.orm.default_entity_manager -> doctrine.dbal.default_connection -> listener -> logger".
The problem obviously is that I inject the doctrine
into the my service while it is also automatically injected into my listener. How do I proceed? I found a very similar question but the accepted answer is to inject the container which is obviously not favourable.
Any suggestions on how to solve my issue would be appreciated.
Small side note: I would like to avoid a solution depending on lazy services if possible.
回答1:
First of all I switched from an EventListener
to an EventSubscriber
. From the docs:
Doctrine defines two types of objects that can listen to Doctrine events: listeners and subscribers. Both are very similar, but listeners are a bit more straightforward.
It turns out one can access the ObjectManager
via the passed $args
-parameter like so:
/** @var Doctrine\Common\Persistence\ObjectManager $manager */
$manager = $args->getObjectManager();
So either use it directly in the callback:
public function postUpdate(LifecycleEventArgs $args)
{
$manager = $args->getObjectManager();
// ...
...or set it to an object field:
/** @var ObjectManager $manager */
private $manager;
public function postUpdate(LifecycleEventArgs $args)
{
$this->manager = $args->getObjectManager();
// ...
回答2:
After struggling with the same problem, I found out that using lazy loading solved my issue.
listener:
class: AppBundle\EventListener\OrderDoctrineListener
tags:
- { name: doctrine.event_listener, event: postPersist, lazy: true }
来源:https://stackoverflow.com/questions/34227467/injecting-entitymanager-dependend-service-into-listener