1

How can I access EntityManager from a command in Symfony 3? It is supposed to be ContainerAware.

This is my code:

use Symfony\Component\Console\Command\Command;
class MyCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $em = $this->getContainer()->getDoctrine();
        ...
    }
}

And I get this error:

Uncaught Symfony\Component\Debug\Exception\UndefinedMethodException: Attempted to call an undefined method named "getContainer" of class "AppBundle\Command\MyCommand"

It happens also if I extend from Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand (which was the symfony 2 way).

Also, injecting Doctrine\ORM\EntityManager in __construct() didn't work.

1
  • 1
    Forget about pulling it from the container. Figure out why injecting the entity manager "did not work". There are plenty of examples on how to do it. Commented Apr 25, 2019 at 11:50

3 Answers 3

2

The best only clean way in 2019 is to use constructor injection. Anything else is being removed in Symfony 3.3/4+, so you only add yourself extra work in the future with $this->get().

Also, injecting Doctrine\ORM\EntityManager in __construct() didn't work

Try Doctrine\ORM\EntityManagerInterface type declaration in __construct().

Also make sure the command has autowire: true in the services.yaml config:

services:
    # in Symfony 3.3+
    _defaults:
        autowire: true

    App\:
        resource: ../src

    # in Symfony 2.8-3.3
    App\SomeCommand:
        autowire: true
Sign up to request clarification or add additional context in comments.

Comments

1

You cannot use getContainer because your command class is not aware of the container.

Make your command extend ContainerAwareCommand

So that you can use getContainer()

 use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

Then extends ContainerAwareCommand :

class MyCommand extends ContainerAwareCommand

And then use it wherever you want :

$em     = $this->getContainer()->get('doctrine')->getManager('default');

EDIT thanks to @tomáš-votruba :

HOWEVER ContainerAware is deprecated in Symfony 4:

Using the EntityManager by injecting it :

So instead of forcefully getting the entity manager with the container, inject in your constructor instead and extend Command by using your command as a service:

namespace App\Command;

use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Console\Command\Command;

class MyCommand extends Command {

//add $entityManager attribute

private $entityManager;

public function __construct(ObjectManager $entityManager)
{
    $this->entityManager= $entityManager;

    // you *must* call the parent constructor
    parent::__construct();
}

As you can see in the constructor, we are injecting the entityManager with ObjectManager which is an interface whereas EntityManager is its ORM implementation, you can do it if you use the default services.yml or one that is set up for autowiring :

# config/services.yaml
services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false       # Allows optimizing the container by removing unused services; this also means
                            # fetching services directly from the container via $container->get() won't work.
                            # The best practice is to be explicit about your dependencies anyway.

3 Comments

This is the worst you can do. Symfony is going away from this approach last 3 years. Use constructor injection
Yep. What Tomas said. The ContainerAwareCommand class is depreciated in S4 and will probably go away completely in S5. Injection is your friend.
@DylanKas Thanks for the update, I've noticed just now your comment :D
0

I would suggest to not inherit from "ContainerAwareCommand" and use "extends Command" again. Generally you should define your command as a service and use dependency injection instead of use "get()" via the container. Just use __constructor injection. That's the way to go, also for commands.

This is how Symfony would suggest it:

https://symfony.com/doc/current/console/commands_as_services.html

3 Comments

This right, but not clear. I prefer more specific response with example. See stackoverflow.com/a/55849164/1348344
Ok i understand. It was the first post and i will explain a lil more in the next ones!
Specific as "with code example". I know what you mean, because I already know the meaning of these words. But if I read your reply asking for this, it's difficult to connect the code with it. Also "Just use __constructor injection.", the author already did it "Also, injecting Doctrine\ORM\EntityManager in __construct() didn't work."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.