Консольные команды
Модуль может добавить в bin/magento собственные команды. Ими удобно запускать то, что не привязано к странице: импорт, пересчёт, проверку данных. Команда — обычный класс на основе компонента Symfony Console, который используется и в других фреймворках.
Где лежит команда
Классы команд кладут в папку Console/Command модуля, а регистрируют в etc/di.xml. Генератора нет — файл создают вручную.
app/code/Acme/Hello/
├── Console/
│ └── Command/
│ └── CountReviews.php новый файл
└── etc/
└── di.xml изменёнКласс команды
// app/code/Acme/Hello/Console/Command/CountReviews.php
namespace Acme\Hello\Console\Command;
use Acme\Hello\Model\ResourceModel\Review\CollectionFactory;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CountReviews extends Command
{
public function __construct(private CollectionFactory $collectionFactory)
{
parent::__construct();
}
protected function configure(): void
{
$this->setName('hello:reviews:count')
->setDescription('Показывает число отзывов');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$count = $this->collectionFactory->create()->getSize();
$output->writeln("<info>Отзывов: $count</info>");
return Command::SUCCESS;
}
}Метод configure() задаёт имя и описание, метод execute() выполняет работу и возвращает код завершения: Command::SUCCESS или Command::FAILURE. Имя принято начинать с названия модуля. В конструкторе обязательно вызывают parent::__construct().
Регистрация
Команду добавляют в список команд через аргумент-массив в di.xml:
<!-- app/code/Acme/Hello/etc/di.xml -->
<type name="Magento\Framework\Console\CommandListInterface">
<arguments>
<argument name="commands" xsi:type="array">
<item name="hello_reviews_count" xsi:type="object">Acme\Hello\Console\Command\CountReviews</item>
</argument>
</arguments>
</type>Это тот самый приём из урока об аргументах: модуль дописывает свой элемент в массив класса ядра.
Запуск
bin/magento cache:clean
bin/magento hello:reviews:countКоманда напечатает Отзывов: 2. Она же появится в списке bin/magento list в группе hello.
Аргументы и параметры
Аргумент — значение после имени команды, параметр — именованный ключ с двумя дефисами. Их объявляют в configure():
// app/code/Acme/Hello/Console/Command/CountReviews.php
use Symfony\Component\Console\Input\InputOption;
protected function configure(): void
{
$this->setName('hello:reviews:count')
->setDescription('Показывает число отзывов')
->addOption('min-rating', null, InputOption::VALUE_REQUIRED, 'Минимальная оценка', 1);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$minRating = (int) $input->getOption('min-rating');
$collection = $this->collectionFactory->create();
$collection->addFieldToFilter('rating', ['gteq' => $minRating]);
$output->writeln('<info>Отзывов: ' . $collection->getSize() . '</info>');
return Command::SUCCESS;
}bin/magento hello:reviews:count --min-rating=5Команда посчитает только отзывы с оценкой пять. Обязательное значение без имени объявляют методом addArgument('file', InputArgument::REQUIRED, 'Описание') и читают через $input->getArgument('file').
Оформление вывода
| Тег | Как выглядит |
|---|---|
info | Зелёный текст |
comment | Жёлтый текст |
error | Белый текст на красном фоне |
Теги пишут прямо в строке, как в примере выше.
Частая ошибка
Magento создаёт объекты всех команд при каждом запуске bin/magento, даже если вызвана чужая команда. Тяжёлая зависимость в конструкторе — сессия, репозиторий товаров — замедляет все команды, а иногда ломает setup:install, когда база ещё пуста. Такие зависимости подставляйте через прокси в di.xml, как показано в уроке об аргументах: объект создастся только при первом обращении.