1

I'm working on a Symfony Single Command Application. I'm using Doctrine to manage entities.

I created the entity configuration using the Symfony CLI and now I'm not sure how I can get access to the EM from within the run method.

Should I create a new subclass of SingleCommandApplication for this?

yivi
  • 42,438
  • 18
  • 116
  • 138
Muc
  • 1,464
  • 2
  • 13
  • 31
  • Take a look at the Doctrine 2 docs to find out how to configure your own entity manager outside of Symfony. Otherwise just use the Symfony skeleton framework and install the Doctrine bundle. – Cerad Nov 30 '21 at 19:18
  • It looks like I already had doctrine-bundle in place... makes sense since I've been using the Doctrine CLI inside the sf app... I'll check out the skeleton. – Muc Nov 30 '21 at 20:46
  • 1
    Your comment about the DoctrineBundle is actually quite confusing. The SingleCommandApp class is used when the Symfony Console component is installed as a standalone package. You certainly will not have any bundles as they require the complete Symfony framework. You might be getting confused about the difference between adding a command to the framework and using the console component standalone. Big difference. – Cerad Dec 01 '21 at 00:21
  • @Cerad you may be right about my confusion. My idea is to put together an application that will only have one command. I thought about using the standard command creation and make it a default but I wanted to try the SingleCommandApp. As for the framework, I have a couple of bundles on my composer.json file and I'm using the maker bundle for creating the entities for instance – Muc Dec 03 '21 at 14:28

2 Answers2

0

If you are truly using a Single Command Application, you'll have to configure Doctrine on your own within the setCode() method. E.g. following these instructions.

(new SingleCommandApplication())
    ->setName('My Super Command') // Optional
    ->setVersion('1.0.0') // Optional
    ->addArgument('foo', InputArgument::OPTIONAL, 'The directory')
    ->addOption('bar', null, InputOption::VALUE_REQUIRED)
    ->setCode(function (InputInterface $input, OutputInterface $output) {

        $paths = array("/path/to/entity-files");
        $isDevMode = false;

        // the connection configuration
        $dbParams = [
            'driver'   => 'pdo_mysql',
            'user'     => 'db_user',
            'password' => 'very_secret',
            'dbname'   => 'foo',
        ];

        $config = Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
        $em     = Doctrine\ORM\EntityManager::create($dbParams, $config);

        // output arguments and options
    })
    ->run();

On a single command application you do not have "bundles" as such, since you are operating outside of the Framework bundle, and generally you wouldn't have access to dependency injection either.

(If you wanted DI, you'd probably have something like this while calling the setDefaultCommand() method on the instantiated Application object, but you'd still need to instantiate the Doctrine connection "manually", even if you are doing on a different service to be injected).

yivi
  • 42,438
  • 18
  • 116
  • 138
  • Hi @yivi thanks for your answer. I used something similar to what you suggest but now I'm having trouble with the ORM mapping. If I use $useSimpleAnnotationReader = true the entity classes are not recognized as such and if I use false the table names' case doesn't match the classes names so it doesn't work either :( – Muc Dec 03 '21 at 14:25
  • Oh, I'm sorry about that. Still, it's bit out of scope for the question, isn't it? That's more of a question of configuration of Doctrine ORM for an existing DB+entities when outside of Symfony, right? – yivi Dec 03 '21 at 14:30
0

Since i just had that question and found this answer here is another way to do it (using php8.1 and symfony 6.2).

I created a Command like described here: https://symfony.com/doc/current/console.html

and just injected the entitymanager via construct and autowiring.

# src/Command/MyCommand

#[AsCommand(name: 'app:my-command',description: 'My Command',hidden: false)]
class HeartbeatCronCommand extends Command
{
    protected static $defaultDescription = 'does stuff';
    protected $entityManager;
    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
        parent::__construct();
    }
    protected function configure(): void
    {
        $this
            ->setHelp('Help');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $client = $this->entityManager->getRepository(Client::class)->findOneByName('test'); # just an example
        return Command::SUCCESS;
    }
}
Ingo
  • 11
  • 2