You are browsing the Symfony 4 documentation, which changes significantly from Symfony 3.x. If your app doesn't use Symfony 4 yet, browse the Symfony 3.4 documentation.

How to Make Commands Lazily Loaded

4.1 version

How to Make Commands Lazily Loaded

Note

If you are using the Symfony full-stack framework, you are probably looking for details about creating lazy commands

The traditional way of adding commands to your application is to use add(), which expects a Command instance as an argument.

In order to lazy-load commands, you need to register an intermediate loader which will be responsible for returning Command instances:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
use App\Command\HeavyCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\CommandLoader\FactoryCommmandLoader;

$commandLoader = new FactoryCommandLoader(array(
    'app:heavy' => function () { return new HeavyCommand() },
));

$application = new Application();
$application->setCommandLoader($commandLoader);
$application->run();

This way, the HeavyCommand instance will be created only when the app:heavy command is actually called.

This example makes use of the built-in FactoryCommandLoader class, but the setCommandLoader() method accepts any CommandLoaderInterface instance so you can use your own implementation.

Built-in Command Loaders

FactoryCommandLoader

The FactoryCommandLoader class provides a simple way of getting commands lazily loaded as it takes an array of Command factories as its only constructor argument:

1
2
3
4
5
6
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;

$commandLoader = new FactoryCommandLoader(array(
    'app:foo' => function () { return new FooCommand() },
    'app:bar' => array(BarCommand::class, 'create'),
));

Factories can be any PHP callable and will be executed each time get() is called.

ContainerCommandLoader

The ContainerCommandLoader class can be used to load commands from a PSR-11 container. As such, its constructor takes a PSR-11 ContainerInterface implementation as its first argument and a command map as its last argument. The command map must be an array with command names as keys and service identifiers as values:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;

$container = new ContainerBuilder();
$container->register(FooCommand::class, FooCommand::class);
$container->compile();

$commandLoader = new ContainerCommandLoader($container, array(
    'app:foo' => FooCommand::class,
));

Like this, executing the app:foo command will load the FooCommand service by calling $container->get(FooCommand::class).

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.