Як зробити команди лінивого завантаження
Дата оновлення перекладу 2024-05-09
Як зробити команди лінивого завантаження
Note
Якщо ви використовуєте повностековий фреймворк Symfony, то ви скоріше за все шукаєте подробиці про створення команд лінивого завантаження
Такий підхід може мати недоліки, оскільки деякі команди можуть бути доволі складними для інстанціювання.
У цьому випадку ви можете скористатися лінивим завантаженням. Зауважте, що ліниве завантаження
не є абсолютним. Насправді, деякі команди, такі як list
, help
або _complete
можуть
можуть вимагати виконання інших команд, хоча вони і є лінивими. Наприклад, команді list
потрібно
отримати ім'я та опис усіх команд, для чого може знадобитися ініціалізація команди.
Для того, щоб ліниво завантажувати команди, вам потрібно зареєструвати серединний
завантажувач, який відопвідатиме за повернення екземпляра Command
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
use App\Command\HeavyCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
$commandLoader = new FactoryCommandLoader([
// Зауважте, що команда `list` все ще інстанціюватиме команду
// в цьому прикладі.
'app:heavy' => static fn(): Command => new HeavyCommand(),
]);
$application = new Application();
$application->setCommandLoader($commandLoader);
$application->run();
Таким чином, екземпляр HeavyCommand
буде створено лише тоді, коли команда
app:heavy
буде дійсно викликана.
Цей приклад використовує вбудований клас FactoryCommandLoader, але метод setCommandLoader() приймає будь-який екземпляр CommandLoaderInterface, так що ви можете використовувати власні реалізації.
Інший спосіб зробити це - скористатися перевагами Symfony
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use App\Command\HeavyCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
// У цьому випадку, хоча команда інстанційована, фабрика команд, що лежить в її основі,
// не буде викликана, доки команду насправді не буде виконано або не буде здійснено спробу доступу до
// її визначення введення, щоб дізнатися введенняі аргументу або опції.
$lazyCommand = new LazyCommand(
'app:heavy',
[],
'Це ще одна більш повна форма лінивої команд.',
false,
static fn (): Command => new HeavyCommand(),
);
$application = new Application();
$application->add($lazyCommand);
$application->run();
Вбудовані завантажувачі команд
FactoryCommandLoader
Клас FactoryCommandLoader
надає простий спосіб отримання команд лінивого завантаження, так як він бере
масив фабрик Command
в якості єдиного аргументу конструктора:
1 2 3 4 5 6 7
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
$commandLoader = new FactoryCommandLoader([
'app:foo' => function (): Command { return new FooCommand(); },
'app:bar' => [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, [
'app:foo' => FooCommand::class,
]);
Таким чином, виконання команди app:foo
завантажить сервіс FooCommand
,
викликавши $container->get(FooCommand::class)
.