A long awaited feature has finally landed in symfony/console 3.4.x-dev: the ability to lazy load commands. There's an article about it on Symfony's blog, but it does not explain how to setup everything. It's not very complex so here we go!
I assume you're using symfony/dependency-injection. If not, you need to create a command loader that implements the CommandLoaderInterface, which is an entirely different story.
First things first, let's create a hello
command:
<?php
namespace App\Presentation\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class HelloCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln("Hello world!");
}
}
Now let's register the command in our container config with the cunning use of tags:
services:
console.command.hello:
class: App\Presentation\Console\Command\HelloCommand
tags:
- { name: console.command, command: hello }
You need to add a compile pass to the container for the magic to happen:
<?php
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
$container = new ContainerBuilder();
// …
$container->addCompilerPass(new AddConsoleCommandPass);
$container->compile();
Finally, create a console
file that will be used to run the CLI application. Note that in my
example, the bootstrap.php
script returns the container:
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Application;
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/* @var ContainerInterface $container */
/* @var CommandLoaderInterface $commandLoader */
$container = require __DIR__ . '/bootstrap.php';
$commandLoader = $container->get('console.command_loader');
$app = new Application();
$app->setCommandLoader($commandLoader);
$app->run();
Don't forget to change the permission to make it executable:
$ chmod +x console
The command can now be executed as follows, and should print "Hello world!":
$ ./console hello
Hello world!
tl;dr
With symfony/console 3.4.x-dev commands can be lazy loaded using a PSR-11 compatible dependency injection container. Of course, they can have their own dependencies, which are resolved just in time when they are actually executed.