Skip to content

[Console] Add more examples for lazy commands #18664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions console/commands_as_services.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,5 @@ only when the ``app:sunshine`` command is actually called.
.. caution::

Calling the ``list`` command will instantiate all commands, including lazy commands.
However, if the command is a ``Symfony\Component\Console\Command\LazyCommand``, then
the underlying command factory will not be executed.
33 changes: 32 additions & 1 deletion console/lazy_commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ The traditional way of adding commands to your application is to use
:method:`Symfony\\Component\\Console\\Application::add`, which expects a
``Command`` instance as an argument.

This approach can have downsides as some commands might be expensive to
instantiate in which case you may want to lazy-load them. Note however that lazy-loading
is not absolute. Indeed a few commands such as `list`, `help` or `_complete` can
require to instantiate other commands although they are lazy. For example `list` needs
to get the name and description of all commands, which might require the command to be
instantiated to get.

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

Expand All @@ -19,7 +26,9 @@ which will be responsible for returning ``Command`` instances::
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;

$commandLoader = new FactoryCommandLoader([
'app:heavy' => function (): Command { return new HeavyCommand(); },
// Note that the `list` command will still instantiate that command
// in this example.
'app:heavy' => static fn(): Command => new HeavyCommand(),
]);

$application = new Application();
Expand All @@ -36,6 +45,28 @@ method accepts any
:class:`Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface`
instance so you can use your own implementation.

Another way to do so is to take advantage of ``Symfony\Component\Console\Command\LazyCommand``::

use App\Command\HeavyCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;

// In this case although the command is instantiated, the underlying command factory
// will not be executed unless the command is actually executed or one tries to access
// to its input definition to know its argument or option inputs.
$lazyCommand = new LazyCommand(
'app:heavy',
[],
'This is another more complete form of lazy command.',
false,
static fn (): Command => new HeavyCommand(),
);

$application = new Application();
$application->add($lazyCommand);
$application->run();

Built-in Command Loaders
------------------------

Expand Down