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


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

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

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

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

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

Author: 7ochem, 2016-04-21

3 answers

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

 6
Author: BuskaMuza, 2016-04-21 20:36:30

Правильный способ:

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

Просто создайте свой 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.');
    }
}
 11
Author: Phoenix128_RiccardoT, 2016-04-21 20:39:24

Если я правильно понял, команды, определенные в списке команд через 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 в файле, загружаемом автоматически композитором (например 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

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

 3
Author: David Verholen, 2016-04-21 20:23:33