Як зробити команди лінивого завантаження

Дата оновлення перекладу 2022-11-19

Як зробити команди лінивого завантаження

Note

Якщо ви використовуєте повностековий фреймворк Symfony, то ви скоріше за все шукаєте подробиці про створення команд лінивого завантаження

Традиційний спосіб додавання команд у ваш додаток - це використання add(), який очікує екземпляр Command в якості аргументу.

Для того, щоб ліниво завантажувати команди, вам потрібно зареєструвати серединний завантажувач, який відопвідатиме за повернення екземпляра Command:

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\FactoryCommandLoader;

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

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

Таким чином, екземпляр HeavyCommand буде створено лише тоді, коли команда app:heavy буде дійсно викликана.

Цей приклад використовує вбудований клас FactoryCommandLoader, але метод setCommandLoader() приймає будь-який екземпляр CommandLoaderInterface, так що ви можете використовувати власні реалізації.

Вбудовані завантажувачі команд

FactoryCommandLoader

Клас FactoryCommandLoader надає простий спосіб отримання команд лінивого завантаження, так як він бере масив фабрик Command в якості єдиного аргументу конструктора:

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'),
));

Фабрики можуть бути будь-яким PHP-викликаним, і будуть виконані кожний раз, коли викликається get().

ContainerCommandLoader

Клас ContainerCommandLoader може бути використано для завантаження команди з контейнера PSR-11. Таким чином, її конструктор бере реалізацію PSR-11 ContainerInterface в якості свого першого аргументу, а мапу команди - в якості останнього. Мапа команди повинна бути масивом з іменами команд в якості ключів та ідентифікаторами сервісів в якості значень:

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,
));

Таким чином, виконання команди app:foo завантажить сервіс FooCommand, викликавши $container->get(FooCommand::class).