Maneira correta e suportada de adicionar comandos da CLI ao Magento 2

9

Existe uma maneira correta e oficialmente suportada de adicionar seus comandos da CLI a um módulo Magento 2? Pelo que reuni suas opções são

  1. Adicione sua classe de comando ao commandsargumento de Magento\Framework\Console\CommandListvia um di.xmlarquivo

  2. Registre seu comando \Magento\Framework\Console\CommandLocator::registerem um registration.phparquivo ou cli_commands.phparquivo

Nenhuma dessas opções é abençoada com um @api. Não está claro, como desenvolvedores de extensões, como devemos adicionar scripts de linha de comando para que eles se mantenham entre versões.

Alguém sabe se existe uma política oficial do Magento na maneira The Right ™ de fazer isso?

Alan Storm
fonte

Respostas:

6

cli_commands.phpdeve ser usado caso o comando seja adicionado em um pacote não modular. Portanto, se o comando estiver no módulo e estiver OK (esperado), ele estará disponível apenas quando o módulo estiver ativado, di.xmldeve ser usado. Se você não deseja adicionar um módulo e deseja ter apenas um pacote arbitrário do Composer, pode usar o cli_commands.phpcomando registrar aqui. Obviamente, deveria ser realmente independente do Magento. Ou, por enquanto, essa abordagem pode ser usada para registrar o (s) comando (s) necessário (s), mesmo que um módulo esteja desativado (verifique se ele não depende da lógica de nenhum módulo que funcione apenas quando ativado).

BuskaMuza
fonte
11

A maneira correta é:

Crie seu módulo como faz para qualquer tipo de módulo

Basta criar seu registration.phparquivo

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'My_Module',
    __DIR__
);

E crie seu module.xmlarquivo:

<?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>

Adicione uma entrada em 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>

Crie sua classe de comando:

<?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!');
    }
}

Para executar sua tarefa, basta digitar:

php bin/magento my:command

Sobre compatibilidade:

O @api não é necessário para comandos, é usado para contratos de serviço AFAIK.

Se você precisar deixá-los compatíveis, basta usar uma API de interface dentro do seu script em vez de colocar a lógica dentro dele.

Por exemplo:

<?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
fonte
11
Informações úteis, +1, mas você tem certeza disso? Os módulos de dados amostra Magento usar o método cli_commands.php, e que parece mais limpo e menos propensos a quebrar se Magento muda a implementação deMagento\Framework\Console\CommandList
Alan Storm
Não tenho 100% de certeza, apenas o Magento em si pode responder a isso, mas já joguei um pouco e, se você remover "cli_commands.php", ainda verá seu comando disponível no seu bin / magento. Eles também os declararam em di.xml, então acho que ainda existe algo da versão beta. Como era para construtores e fábricas. Se você vir, cli_command.php é usado apenas em dados de amostra.
precisa saber é o seguinte
O que faz você dizer que o @api ficará obsoleto?
Kristof em Fooman
@ Kristof, desculpe não ter entendido corretamente um dos slides da solução de parceiro treinado, então ignore essa frase. Modifiquei minha postagem removendo-a.
Phoenix128_RiccardoT
3

se eu entendi direito, os comandos definidos na CommandList sobre DI estão disponíveis apenas em uma instância Magento instalada e também apenas nos módulos Magento (uma vez que precisam ser definidos no di.xml): https://github.com/magento /magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L124

o Magento \ Framework \ App \ DeploymentConfig :: isAvailable () no método acima verifica uma Data de instalação no Config para verificar se há um Magento2 instalado: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/ interno / Magento / Framework / App / DeploymentConfig.php # L83 ).

Os comandos definidos no Magento \ Framework \ Console \ CommandLocator, por outro lado, estão sempre disponíveis e podem ser definidos por módulos não Magento através do método estático CommandLocator :: register em um arquivo carregado automaticamente pelo compositor (por exemplo, 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

Então eu acho que os dois métodos são necessários e têm o direito de existir

David Verholen
fonte
Essa é uma boa observação +1, mas por que você precisa de um script Magento enquanto o módulo relacionado não está instalado?
precisa saber é o seguinte
11
é sobre a instância do magento não estar instalada. Existem vários comandos disponíveis antes de instalar o magento2. Por exemplo, o comando sampledata: deploy, que faz sentido se você deseja instalar diretamente os dados de amostra com a configuração do magento2.
21716 David Verholen
Eu acho que você está certo. Portanto, a maneira "correta" para um módulo Magento é usar di.xml (como na minha resposta) e usar "cli_command.php" quando você precisar executar alguma tarefa antes de instalar o módulo. Faz sentido.
Phoenix128_RiccardoT
sim, acho que deveria ser isso. +1 porque eu acho que você tem o direito (e muito bem explicado) resposta, mas isso não se encaixam em um comentário;)
David Verholen
Obrigado @ David Verholen, meu +1 foi o que significa que eu te dei um, não que você merecia apenas uma +1;)
Phoenix128_RiccardoT