Santi
Santi

Reputation: 509

Access to database in a listener in Symfony 2

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

Answers (6)

Ghazaleh Javaheri
Ghazaleh Javaheri

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

solarc
solarc

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

webDEVILopers
webDEVILopers

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

dazz
dazz

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

simshaun
simshaun

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

Alessandro Desantis
Alessandro Desantis

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

Related Questions