Как сделать команды ленивой загрузки
Как сделать команды ленивой загрузки
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)
.