Правильный, поддерживаемый способ добавления команд CLI в Magento 2
Вопрос
Существует ли правильный и официально поддерживаемый способ добавления ваших команд CLI в модуль Magento 2?Из того, что я собрал, у вас есть следующие варианты
Добавьте свой командный класс в
commands
аргумент оMagento\Framework\Console\CommandList
через adi.xml
файлЗарегистрируйте свою команду через
\Magento\Framework\Console\CommandLocator::register
вregistration.php
файл илиcli_commands.php
файл
Ни один из этих вариантов не наделен @api
.Нам, разработчикам расширений, неясно, как мы должны добавлять сценарии командной строки, чтобы они сохранялись от версии к версии.
Кто-нибудь знает, существует ли официальная политика Magento относительно правильного ™ способа сделать это?
Решение
cli_commands.php
следует использовать в случае, если команда добавлена в немодульный пакет.Итак, если команда находится в модуле, и это нормально (ожидается), что она доступна только тогда, когда модуль включен, di.xml
должен быть использован.Если вы не хотите добавлять модуль и хотите иметь только произвольный пакет Composer, вы можете использовать cli_commands.php
зарегистрировать команду там.Конечно, тогда он должен быть действительно независимым от Magento.Или, на данный момент, этот подход можно использовать для регистрации необходимых команд, даже если модуль отключен (убедитесь, что он не полагается на логику какого-либо модуля, которая работает только тогда, когда она включена).
Другие советы
Правильный способ - это:
Создайте свой модуль так же, как вы делаете для любого другого модуля
Просто создайте свой registration.php
файл
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'My_Module',
__DIR__
);
И создать тебя module.xml
файл:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="My_Module" setup_version="0.1.0">
</module>
</config>
Добавьте запись в di.xml
:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Console\CommandList">
<arguments>
<argument name="commands" xsi:type="array">
<item name="my_command" xsi:type="object">My\Module\Command\Mycommand</item>
</argument>
</arguments>
</type>
</config>
Создайте свой командный класс:
<?php
namespace My\Module\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Mycommand extends Command
{
protected function configure()
{
$this->setName('my:command');
$this->setDescription('Run some task');
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Hello world!');
}
}
Чтобы выполнить свою задачу, просто введите:
php bin/magento my:command
О совместимости:
@api не нужен для команд, он используется для контракты на обслуживание АФАИК.
Если вам нужно обеспечить их совместимость, просто используйте интерфейс API внутри вашего скрипта вместо того, чтобы помещать в него логику.
Например:
<?php
use My\Module\Api\TaskInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends Command
{
protected $taskInterface;
public function __construct(
TaskInterface $taskInterface
) {
$this->taskInterface= $taskInterface;
parent::__construct();
}
protected function configure()
{
$this->setName('my:command');
$this->setDescription('Run some task');
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->taskInterface->runTask();
$output->writeln('Done.');
}
}
если я правильно понял, команды, определенные в списке команд через DI, доступны только в установленном экземпляре Magento, а также только для модулей Magento (поскольку они должны быть определены в di.xml): https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L124
Magento\Framework\App\DeploymentConfig::isAvailable() в приведенном выше методе проверяет дату установки в конфигурации, чтобы проверить наличие установленного Magento2: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/App/DeploymentConfig.php#L83).
Команды, определенные в Magento\Framework\Console\CommandLocator, с другой стороны, всегда доступны и даже могут быть определены модулями, отличными от Magento, с помощью статического метода CommandLocator::register в файле, автоматически загружаемом composer (например cli_commands.php )
Поэтому я думаю, что оба метода необходимы и имеют свое право на существование