|
| 1 | +How to Make Commands Lazily Loaded |
| 2 | +================================== |
| 3 | + |
| 4 | +.. versionadded:: 3.4 |
| 5 | +Support for command lazy loading was introduced in Symfony 3.4. |
| 6 | + |
| 7 | +.. note:: |
| 8 | +If you are using the Symfony full-stack framework, you are probably looking for |
| 9 | +:ref:`lazy loading of commands defined as services <console-command-service-lazy-loading>` |
| 10 | + |
| 11 | +The traditional way of adding commands to your application is to use |
| 12 | +:method:`Symfony\\Component\\Console\\Application::add` which expects a |
| 13 | +``Command`` instance as argument. |
| 14 | +In order to get commands loaded lazily, you need to register an intermediate router |
| 15 | +which will be responsible for returning ``Command`` instances:: |
| 16 | + |
| 17 | + use AppBundle\Command\HeavyCommand; |
| 18 | + use Symfony\Component\Console\Application; |
| 19 | + use Symfony\Component\Console\CommandLoader\FactoryCommmandLoader; |
| 20 | + |
| 21 | + $commandLoader = new FactoryCommandLoader(array( |
| 22 | + 'app:heavy' => function () { return new HeavyCommand() }, |
| 23 | + )); |
| 24 | + |
| 25 | + $application = new Application(); |
| 26 | + $application->setCommandLoader($commandLoader); |
| 27 | + $application->run(); |
| 28 | + |
| 29 | +This way, the ``HeavyCommand`` instance will be created only when the ``app:foo`` |
| 30 | +command is actually called. |
| 31 | + |
| 32 | +This example makes use of the built-in |
| 33 | +:class:`Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader` class, |
| 34 | +but the :method:`Symfony\\Component\\Console\\Application::setCommandLoader` |
| 35 | +method accepts any |
| 36 | +:class:`Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface` |
| 37 | +instance so you can easily create and use your own implementation. |
| 38 | + |
| 39 | +Built-in Command Loaders |
| 40 | +------------------------ |
| 41 | + |
| 42 | +``FactoryCommandLoader`` |
| 43 | +~~~~~~~~~~~~~~~~~~~~~~~~ |
| 44 | + |
| 45 | +The :class:`Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader` |
| 46 | +class provides a simple way of getting commands lazily loaded as it takes an |
| 47 | +array of ``Command`` factories as only constructor argument:: |
| 48 | + |
| 49 | + use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; |
| 50 | + |
| 51 | + $commandLoader = new FactoryCommandLoader(array( |
| 52 | + 'app:foo' => function () { return new FooCommand() }, |
| 53 | + 'app:bar' => array(BarCommand::class, 'create'), |
| 54 | + )); |
| 55 | + |
| 56 | +Factories can be any PHP callable and will be executed each time |
| 57 | +:method:`Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader::get` |
| 58 | +is called. |
| 59 | + |
| 60 | +``ContainerCommandLoader`` |
| 61 | +~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 62 | + |
| 63 | +The :class:`Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader` |
| 64 | +class can be used to load commands from a PSR-11 container. |
| 65 | +As such, its constructor takes a PSR-11 ``ContainerInterface`` implementation as |
| 66 | +first argument and a command map as last argument. The command map must be an array |
| 67 | +with command names as keys and service identifiers as values:: |
| 68 | + |
| 69 | + use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; |
| 70 | + use Symfony\Component\DependencyInjection\ContainerBuilder; |
| 71 | + |
| 72 | + $container = new ContainerBuilder(); |
| 73 | + $container->register(FooCommand::class, FooCommand::class); |
| 74 | + $container->compile(); |
| 75 | + |
| 76 | + $commandLoader = new ContainerCommandLoader($container, array( |
| 77 | + 'app:foo' => FooCommand::class, |
| 78 | + )); |
| 79 | + |
| 80 | +Like this, executing the `app:foo` command will load the ``FooCommand`` service |
| 81 | +by calling ``$container->get(FooCommand::class)``. |
0 commit comments