Правильный, поддерживаемый способ добавления команд консоли в Magento 2

9

Существует ли правильный и официально поддерживаемый способ добавления команд CLI в модуль Magento 2? Из того, что я собрал ваши варианты

  1. Добавьте свой класс команды к commandsаргументу Magento\Framework\Console\CommandListчерез di.xmlфайл

  2. Зарегистрируйте свою команду с помощью \Magento\Framework\Console\CommandLocator::registerв registration.phpфайл или cli_commands.phpфайл

Ни один из этих вариантов не наделен @api. Как разработчики расширений, не ясно, как мы должны добавлять сценарии командной строки, чтобы они придерживались версии в версии.

Кто-нибудь знает, есть ли официальная политика Magento относительно способа сделать это?

Алан Сторм
источник

Ответы:

6

cli_commands.phpследует использовать, если команда добавлена ​​в немодульный пакет. Поэтому, если команда находится в модуле и все в порядке (ожидается), что она доступна только тогда, когда модуль включен, di.xmlследует использовать. Если вы не хотите добавлять модуль и хотите иметь произвольный пакет Composer, вы можете использовать cli_commands.phpдля регистрации команды там. Конечно, тогда он должен быть действительно независимым от Magento. Или, на данный момент, этот подход можно использовать для регистрации необходимых команд, даже если модуль отключен (убедитесь, что он не полагается на логику какого-либо модуля, которая работает только при его включении).

BuskaMuza
источник
11

Правильный путь:

Создайте свой модуль, как вы делаете для любого вида модуля

Просто создайте свой 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 не нужен для команд, он используется для сервисных контрактов AFAIK.

Если вам нужно сделать их совместимыми, просто используйте интерфейсный 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.');
    }
}
Phoenix128_RiccardoT
источник
1
Полезная информация, +1, но уверены ли вы в этом? Модули с примерами данных Magento используют метод cli_commands.php, и он кажется более чистым и менее вероятен, если Magento изменит реализациюMagento\Framework\Console\CommandList
Alan Storm
Я не уверен на 100%, только Magento сама может ответить на этот вопрос, но я играл на нем некоторое время, и если вы удалите «cli_commands.php», вы все равно увидите свою команду доступной в вашем bin / magento. Они также объявили их в di.xml, так что я думаю, что это просто что-то еще из бета-версии. Как это было для строителей и заводов. Если вы видите, cli_command.php используется только в sample-data.
Phoenix128_RiccardoT
Что заставляет вас говорить, что @api станет устаревшим?
Кристоф в Фумане
@Kristof, извините, я не правильно понял слайд с обученным партнерским решением, поэтому проигнорируйте это предложение. Я изменил свой пост, удалив его.
Phoenix128_RiccardoT
3

если я правильно понял, команды, определенные в CommandList over 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/6352f8fbca2cbf21de88db0cf7f4555bfb60601 internal / Magento / Framework / App / DeploymentConfig.php # L83 ).

С другой стороны, команды, определенные в Magento \ Framework \ Console \ CommandLocator, всегда доступны и даже могут быть определены не Magento-модулями через статический метод CommandLocator :: register в файле, автоматически загружаемом композитором (например, cli_commands.php)

https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L130

https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L146

Поэтому я думаю, что оба метода необходимы и имеют право на существование

Дэвид Верхолен
источник
Это хорошее замечание +1, но зачем вам нужен скрипт на Magento, пока соответствующий модуль не установлен?
Phoenix128_RiccardoT
1
о magento экземпляр не установлен. Перед установкой magento2 доступно несколько команд. Например, команда sampledata: deploy, которая имеет смысл, если вы хотите напрямую установить пример данных с помощью настройки magento2.
Дэвид Верхолен
Я думаю, вы правы. Таким образом, «правильный» способ для модуля Magento - это использовать di.xml (как в моем ответе) и использовать «cli_command.php», когда вам нужно запустить какую-то задачу перед установкой вашего модуля. Это имеет смысл.
Phoenix128_RiccardoT
да, я думаю, что так и должно быть. +1, потому что я думаю, что у вас есть правильный (и очень хорошо объясненный) ответ, но это не
вписалось
Спасибо, Дэвид Верхолен, мой +1 означал, что я дал тебе +1, а не то, что ты заслужил просто +1;)
Phoenix128_RiccardoT