Pregunta

¿Existe una forma correcta y oficialmente compatible de agregar sus comandos CLI a un módulo Magento 2?Por lo que he recopilado, tus opciones son

  1. Agregue su clase de comando al commands argumento de Magento\Framework\Console\CommandList a través de di.xml archivo

  2. Registre su comando a través de \Magento\Framework\Console\CommandLocator::register en un registration.php archivo o un cli_commands.php archivo

Ninguna de estas opciones está bendecida con una @api.No está claro, como desarrolladores de extensiones, cómo debemos agregar secuencias de comandos de línea de comandos de modo que se mantengan de una versión a otra.

¿Alguien sabe si existe una política oficial de Magento sobre la forma The Right™ de hacer esto?

¿Fue útil?

Solución

cli_commands.php debe usarse en caso de que el comando se agregue en un paquete no modular.Entonces, si el comando está en el módulo y está bien (se espera) que esté disponible solo cuando el módulo esté habilitado, di.xml debería ser usado.Si no desea agregar un módulo y desea tener solo un paquete Composer arbitrario, puede usar cli_commands.php para registrar el comando allí.Por supuesto, debería ser realmente independiente de Magento.O, por ahora, este enfoque se puede utilizar para registrar comandos necesarios incluso si un módulo está deshabilitado (asegúrese de que no dependa de la lógica de ningún módulo que funcione solo cuando esté habilitado).

Otros consejos

La forma correcta es:

Crea tu módulo como lo haces para cualquier tipo de módulo.

Simplemente crea tu registration.php archivo

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

y crearte module.xml archivo:

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

Añadir una entrada en 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>

Crea tu clase 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 ejecutar su tarea simplemente escriba:

php bin/magento my:command

Acerca de la compatibilidad:

@api no es necesario para los comandos, se usa para contratos de servicio HASTA DONDE SE.

Si necesita hacerlos compatibles, simplemente use un API de interfaz dentro de su script en lugar de poner la lógica dentro de él.

Por ejemplo:

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

Si lo hice bien, los comandos definidos en CommandList a través de DI solo están disponibles en una instancia de Magento instalada y también solo para módulos Magento (ya que deben definirse en di.xml): https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L124

Magento\Framework\App\DeploymentConfig::isAvailable() en el método anterior busca una fecha de instalación en la configuración para verificar si hay un Magento2 instalado: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/App/DeploymentConfig.php#L83).

Por otro lado, los comandos definidos en Magento\Framework\Console\CommandLocator siempre están disponibles e incluso pueden ser definidos por módulos que no sean Magento a través del método estático CommandLocator::register en un archivo cargado automáticamente por el compositor (por ejemplo, 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

Por eso creo que ambos métodos son necesarios y tienen derecho a existir.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a magento.stackexchange
scroll top