Richtige, unterstützte Methode zum Hinzufügen von CLI-Befehlen zu Magento 2
Frage
Gibt es eine korrekte und offiziell unterstützte Möglichkeit, Ihre CLI-Befehle zu einem Magento 2-Modul hinzuzufügen?Soweit ich weiß, stehen Ihnen folgende Optionen zur Verfügung
Fügen Sie Ihre Befehlsklasse zum hinzu
commands
Argument vonMagento\Framework\Console\CommandList
über eindi.xml
DateiRegistrieren Sie Ihren Befehl über
\Magento\Framework\Console\CommandLocator::register
in einemregistration.php
Datei oder einecli_commands.php
Datei
Keine dieser Optionen ist mit einem gesegnet @api
.Als Erweiterungsentwickler ist es nicht klar, wie wir Befehlszeilenskripts hinzufügen sollen, damit sie von Version zu Version erhalten bleiben.
Weiß jemand, ob es eine offizielle Magento-Richtlinie für die Vorgehensweise von The Right™ gibt?
Lösung
cli_commands.php
sollte verwendet werden, falls der Befehl in einem nicht modularen Paket hinzugefügt wird.Wenn sich der Befehl also im Modul befindet und es in Ordnung (erwartet) ist, dass er nur verfügbar ist, wenn das Modul aktiviert ist, di.xml
sollte benutzt werden.Wenn Sie kein Modul hinzufügen möchten und nur ein beliebiges Composer-Paket haben möchten, können Sie es verwenden cli_commands.php
um dort den Befehl zu 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 basiert, das nur funktioniert, wenn es aktiviert ist).
Andere Tipps
Der richtige Weg ist:
Erstellen Sie Ihr Modul wie jedes andere Modul auch
Erstellen Sie einfach Ihr registration.php
Datei
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'My_Module',
__DIR__
);
Und erschaffe dich module.xml
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 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
Zur Kompatibilität:
@api wird für Befehle nicht benötigt, sondern für verwendet Dienstleistungsverträge SO VIEL ICH WEISS.
Wenn Sie sie kompatibel machen möchten, verwenden Sie einfach eine Schnittstellen-API in Ihr Skript integrieren, 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.');
}
}
Wenn ich es richtig verstanden habe, sind in der CommandList über DI definierte Befehle nur in einer installierten Magento-Instanz und auch nur für Magento-Module verfügbar (da sie in der 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 nach einem Installationsdatum in der Konfiguration, um nach einem installierten Magento2 zu suchen: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/App/DeploymentConfig.php#L83).
Die im Magento\Framework\Console\CommandLocator definierten Befehle sind hingegen immer verfügbar und können sogar von Nicht-Magento-Modulen über die statische CommandLocator::register-Methode in einer vom Composer automatisch geladenen Datei definiert werden (z. B. cli_commands.php).
Daher denke ich, dass beide Methoden notwendig sind und ihre Daseinsberechtigung haben