Reputation: 509
We need to access to database info in a listener. We configure the listener in a service.yml The listener is like:
namespace company\MyBundle\Listener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class RequestListener
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function onKernelRequest(GetResponseEvent $event)
{
...
How can we access to doctrine at onKernelRequest function?
I tried to extends from controller and do:
$em = $this->getDoctrine()->getEntityManager();
and it works but I think this is a bad practice.
Upvotes: 10
Views: 14406
Reputation: 2117
in symfony 4 you should use dependency injection like this
class eventSubscriber implements EventSubscriberInterface
{
/**
* @var EntityManagerInterface
*/
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
}
Upvotes: 0
Reputation: 5738
You can just inject the service container. First change the constructor to get an EntityManager:
use Doctrine\ORM\EntityManager;
class RequestListener {
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
//...
}
And next configure your service:
#...
services:
foo.requestlistener:
class: %foo.requestlistener.class%
arguments:
- @doctrine.orm.entity_manager
Upvotes: 31
Reputation: 1916
If your use case allows you to use a Doctrine Event Listener directely
#services.yml
qis.listener.contractBundleStatusListener:
class: Acme\AppBundle\EventListener\MyListener
tags:
- { name: doctrine.event_listener, event: postPersist }
you can get the Entity Manager from the LifecycleEventArgs:
<?php
use Doctrine\ORM\Event\LifecycleEventArgs;
class MyListener
{
public function postPersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof Foo) {
$entityManager = $args->getEntityManager();
$entityManager->persist($entity);
$entityManager->flush();
}
}
}
Upvotes: 3
Reputation: 96
I would not put business logic to listeners as the are only for listening to events. And how would you write tests for the listener using doctrine ...
I'd put the doctrine accessing stuff to a different class and then call it in the listener.
Upvotes: 0
Reputation: 21476
I'm kind of a novice at Symfony still, but have you tried passing the doctrine
service to your listener instead of the service container?
Alternately, you are already passing the service container, so it should be as simple as calling $this->container->get('doctrine')
. Also, I was told in IRC some time ago that passing the service container is usually considered bad practice. It's better to pass the individual services that you need.
Upvotes: 1
Reputation: 14343
It seems like you're injecting the service container into the listener, so you can access Doctrine this way:
$doctrine = $this->container->get('doctrine');
Upvotes: 3