How to use my Entities and Entity Managers in Symfony 2 Console Command?

38,422

Solution 1

I think you should not retrieve the container in the constructor directly. Instead, retrieve it in the configure method or in the execute method. In my case, I get my entity manager just at the start of the execute method like this and everything is working fine (tested with Symfony 2.1).

protected function execute(InputInterface $input, OutputInterface $output)
{
    $entityManager = $this->getContainer()->get('doctrine')->getEntityManager();

    // Code here
}

I think that the instantiation of the application object is not done yet when you are calling getContainer in your constructor which result in this error. The error comes from the getContainer method tyring to do:

$this->container = $this->getApplication()->getKernel()->getContainer();

Since getApplication is not an object yet, you get the a error saying or are calling a method getKernel on a non-object.

Update: In newer version of Symfony, getEntityManager has been deprecated (and could have been removed altogether by now). Use $entityManager = $this->getContainer()->get('doctrine')->getManager(); instead. Thanks to Chausser for pointing it.

Update 2: In Symfony 4, auto-wiring can be used to reduce amount of code needed.

Create a __constructor with a EntityManagerInterface variable. This variable will be accessible in the rest of your commands. This follows the auto-wiring Dependency Injection scheme.

class UserCommand extends ContainerAwareCommand { 
  private $em; 

  public function __construct(?string $name = null, EntityManagerInterface $em) { 
    parent::__construct($name); 

    $this->em = $em;
  } 

  protected function configure() { 
    **name, desc, help code here** 
  }

  protected function execute(InputInterface $input, OutputInterface $output) { 
    $this->em->getRepository('App:Table')->findAll();
  }
}

Credits to @profm2 for providing the comment and the code sample.

Solution 2

extends your command class from ContainerAwareCommand instead of Command

class YourCmdCommand extends ContainerAwareCommand

and get entity manager like this :

$em = $this->getContainer()->get('doctrine.orm.entity_manager');

Solution 3

I know that Matt's answer solved the question, But if you've more than one entity manager, you can use this:

Make model.xml with:

<?xml version="1.0" encoding="UTF-8" ?>

<container xmlns="http://symfony.com/schema/dic/services"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://symfony.com/schema/dic/services         http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
    <service id="EM_NAME.entity_manager" alias="doctrine.orm.entity_manager" />
</services>
</container>

Then load this file in your DI extension

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('model.xml');

Then you can use it anywhere. In Console Command execute:

$em = $this->getContainer()->get('EM_NAME.entity_manager');

and don't forget at end to :

$em->flush();

You can now use it as a argument in another service in services.yml:

services:
    SOME_SERVICE:
        class: %parameter.class%
        arguments:
            - @EM_NAME.entity_manager

Hope this help someone.

Share:
38,422
Fester Bestertester
Author by

Fester Bestertester

Updated on July 09, 2022

Comments

  • Fester Bestertester
    Fester Bestertester almost 2 years

    I want to a few terminal commands to my Symfony2 application. I've gone through the example in the cookbook, but I couldn't find out how to access my settings, my entity manager and my entities here. In the constructor, I get the container (which should yield me access to settings and entities) using

    $this->container = $this->getContainer();
    

    But this call generates an error:

    Fatal error: Call to a member function getKernel() on a non-object in /Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php on line 38

    Basically, in ContainerAwareCommand->getContainer() the call to

    $this->getApplication()
    

    returns NULL and not an object as expected. I guess that I left some important step out, but which one? And how will I finally be able to use my settings and entities?

  • Fester Bestertester
    Fester Bestertester over 12 years
    I had that one figured out already, but as a newb, I couldn't answer my own question. You can't get the container in the constructor, as it doesn't exist yet. It all works beautifully if you retrieve the container in the execute method. After that, you have access to your Entities the usual way: $myEntities = $em->getRepository('Acme\DemoBundle:Myentity')->findAll();
  • Chase
    Chase almost 11 years
    With the latest version ->getEntityManager(); is now deprecated in favor of ->getManager();
  • tuxone
    tuxone about 10 years
    Remember to extend ContainerAwareCommand instead of Command in order to access getContainer() method
  • Remy Mellet
    Remy Mellet about 8 years
    AND the command class must be in the command folder eg: AppBundle\Command package AND you must call the command using "bin/console mycommand" see symfony.com/doc/current/cookbook/console/…
  • profm2
    profm2 over 6 years
    In Symfony 4, create a __constructor with a EntityManagerInterface variable. This variable will be accessible in the rest of your commands. This follows the autowiring/dependencyInjection scheme.
  • Matt
    Matt over 6 years
    @profm2 OK with you if I copy verbatim your comment in the answer? I don't do much Symfony nowaday.
  • profm2
    profm2 over 6 years
    class UserCommand extends ContainerAwareCommand { private $em; public function __construct(?string $name = null, EntityManagerInterface $em) { parent::__construct($name); $this->em = $em; } protected function configure() { **name, desc, help code here** } protected function execute(InputInterface $input, OutputInterface $output) { $this->em->getRepository('App:Table')->findAll(); **etc etc** } }
  • profm2
    profm2 over 6 years
    @Matt Sure thing. The code above is for Symfony 4.0.
  • Muc
    Muc over 5 years
    A small addendum: don't forget to put the use Doctrine\ORM\EntityManagerInterface; at the top
  • Isengo
    Isengo over 5 years
    ContainerAwareCommand is deprecated since 4.2 - any solution for the use later on?
  • Isengo
    Isengo over 5 years
    ContainerAwareCommand is deprecated since 4.2 - any solution for the use later on?
  • stloc
    stloc over 5 years
    @Isengo show other more recents responses because my suggestion are too old
  • vim
    vim over 5 years
    @Isengo As of Symfony 4.2 you can inject the Doctrine\ORM\EntityManagerInterface into the Command.