Access to database in a listener in Symfony 2

13,841

Solution 1

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

Solution 2

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();
        }
    }
}

Solution 3

It seems like you're injecting the service container into the listener, so you can access Doctrine this way:

$doctrine = $this->container->get('doctrine');

Solution 4

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.

Share:
13,841
Santi
Author by

Santi

Tech lead &amp; software developer. DDD, ES, CQRS, Php, Symfony4. Interested in Go, Kotlin

Updated on June 13, 2022

Comments

  • Santi
    Santi almost 2 years

    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.

  • someuser
    someuser about 11 years
    Thanks that worked once I added "use Symfony\Component\DependencyInjection\ContainerInterface;"
  • Dayron Gallardo
    Dayron Gallardo almost 5 years
    You still need to configure the service and pass the EntityManager service, otherwise, you will have an auto-wire error.