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

magento.stackexchange https://magento.stackexchange.com/questions/112022

Вопрос

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

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

  2. Зарегистрируйте свою команду через \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 )

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с magento.stackexchange
scroll top