Richtige, unterstützte Methode zum Hinzufügen von CLI-Befehlen zu Magento 2

9

Gibt es eine korrekte und offiziell unterstützte Möglichkeit, Ihre CLI-Befehle einem Magento 2-Modul hinzuzufügen? Nach dem, was ich gesammelt habe, sind Ihre Optionen

  1. Fügen Sie Ihre Befehlsklasse über eine Datei zum commandsArgument von hinzuMagento\Framework\Console\CommandListdi.xml

  2. Registrieren Sie Ihren Befehl über \Magento\Framework\Console\CommandLocator::registerin einer registration.phpDatei oder einer cli_commands.phpDatei

Keine dieser Optionen ist mit einem gesegnet @api. Als Erweiterungsentwickler ist nicht klar, wie wir Befehlszeilenskripte hinzufügen sollen, damit sie von Version zu Version bleiben.

Weiß jemand, ob es eine offizielle Magento-Richtlinie für The Right ™ gibt, um dies zu tun?

Alan Storm
quelle

Antworten:

6

cli_commands.phpsollte verwendet werden, wenn der Befehl in einem nicht modularen Paket hinzugefügt wird. Wenn sich der Befehl im Modul befindet und OK (erwartet) ist, dass er nur verfügbar ist, wenn das Modul aktiviert ist, di.xmlsollte er verwendet werden. Wenn Sie kein Modul hinzufügen und nur ein beliebiges Composer-Paket haben möchten, können Sie cli_commands.phpdort den Befehl registrieren. Natürlich sollte es dann wirklich unabhängig von Magento sein. Oder dieser Ansatz kann vorerst verwendet werden, um Befehle zu registrieren, die auch dann erforderlich sind, wenn ein Modul deaktiviert ist (stellen Sie sicher, dass es nicht auf der Logik eines Moduls beruht, die nur funktioniert, wenn es aktiviert ist).

BuskaMuza
quelle
11

Der richtige Weg ist:

Erstellen Sie Ihr Modul wie für jede Art von Modul

Erstellen Sie einfach Ihre registration.phpDatei

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

Und erstellen Sie module.xmlIhre Datei:

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

Fügen Sie einen Eintrag hinzu in 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>

Erstellen Sie Ihre Befehlsklasse:

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

Um Ihre Aufgabe auszuführen, geben Sie einfach Folgendes ein:

php bin/magento my:command

Informationen zur Kompatibilität:

@api wird für Befehle nicht benötigt, es wird für Serviceverträge AFAIK verwendet.

Wenn Sie sie kompatibel lassen möchten, verwenden Sie einfach eine Schnittstellen-API in Ihrem Skript, anstatt die Logik darin zu platzieren.

Zum Beispiel:

<?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
quelle
1
Nützliche Informationen, +1, aber sind Sie sich da sicher? Die Magento-Beispieldatenmodule verwenden die Methode cli_commands.php, und das scheint sauberer zu sein und weniger wahrscheinlich zu brechen, wenn Magento die Implementierung vonMagento\Framework\Console\CommandList
Alan Storm am
Ich bin nicht 100% sicher, nur Magento selbst kann dies beantworten, aber ich habe eine Weile darauf gespielt und wenn Sie "cli_commands.php" entfernen, wird Ihr Befehl immer noch in Ihrem bin / magento verfügbar sein. Sie haben sie auch auf di.xml deklariert, also denke ich, dass es nur noch etwas von der Beta-Version gibt. Wie es für Bauherren und Fabriken war. Wenn Sie sehen, wird cli_command.php nur in Beispieldaten verwendet.
Phoenix128_RiccardoT
Was lässt Sie sagen, dass @api veraltet sein wird?
Kristof bei Fooman
@Kristof, es tut mir leid, dass ich eine der geschulten Partnerlösungsfolien nicht richtig verstanden habe. Ignorieren Sie diesen Satz. Ich habe meinen Beitrag geändert und ihn entfernt.
Phoenix128_RiccardoT
3

Wenn ich es richtig verstanden habe, sind in der Befehlsliste über DI definierte Befehle nur in einer installierten Magento-Instanz und auch nur für Magento-Module verfügbar (da sie in der Datei di.xml definiert werden müssen): https://github.com/magento /magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L124

Magento \ Framework \ App \ DeploymentConfig :: isAvailable () in der obigen Methode sucht in der Konfiguration nach einem Installationsdatum, um nach einem installierten Magento2 zu suchen: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451 intern / Magento / Framework / App / DeploymentConfig.php # L83 ).

Die im Magento \ Framework \ Console \ CommandLocator definierten Befehle sind dagegen immer verfügbar und können sogar von Nicht-Magento-Modulen über die statische CommandLocator :: register-Methode in einer vom Composer automatisch geladenen Datei (z. B. cli_commands.php) definiert werden.

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

Ich denke also, dass beide Methoden benötigt werden und das Recht haben zu existieren

David Verholen
quelle
Das ist eine gute Beobachtung +1, aber warum sollten Sie ein Magento-Skript benötigen, während das zugehörige Modul nicht installiert ist?
Phoenix128_RiccardoT
1
Es geht darum, dass die Magento-Instanz nicht installiert ist. Vor der Installation von magento2 stehen mehrere Befehle zur Verfügung. Zum Beispiel der Befehl sampledata: deploy, der sinnvoll ist, wenn Sie die Beispieldaten direkt mit magento2 setup installieren möchten.
David Verholen
Ich glaube, Du hast recht. Der "richtige" Weg für ein Magento-Modul besteht darin, di.xml (wie in meiner Antwort) und "cli_command.php" zu verwenden, wenn Sie eine Aufgabe ausführen müssen, bevor Ihr Modul installiert wird. Es macht Sinn.
Phoenix128_RiccardoT
Ihr, ich denke das sollte es sein. +1 weil ich denke du hast die richtige (und sehr gut erklärte) Antwort, aber das passte nicht in einen Kommentar;)
David Verholen
Danke @David Verholen, meine +1 bedeutete, dass ich dir +1 gegeben habe, nicht dass du nur eine +1 verdient hättest;)
Phoenix128_RiccardoT