是否有正确且官方支持的方法将 CLI 命令添加到 Magento 2 模块?根据我收集的信息,你的选择是

  1. 将您的命令类添加到 commands 的论证 Magento\Framework\Console\CommandList 通过一个 di.xml 文件

  2. 通过注册您的命令 \Magento\Framework\Console\CommandLocator::register 在一个 registration.php 文件或一个 cli_commands.php 文件

这些选项都没有被祝福 @api. 。作为扩展开发人员,尚不清楚我们应该如何添加命令行脚本,以便它们能够在版本之间保持一致。

有谁知道 Magento 是否有关于 The Right™ 方式的官方政策?

有帮助吗?

解决方案

cli_commands.php 如果该命令添加到非模块化包中,则应使用该命令。因此,如果该命令位于模块中,并且仅当模块启用时它才可用,这是可以的(预期), di.xml 应该使用。如果您不想添加模块而只想拥有任意 Composer 包,您可以使用 cli_commands.php 在那里注册命令。当然,它应该真正独立于 Magento。或者,目前,即使模块被禁用,此方法也可用于注册必要的命令(确保它不依赖于任何仅在启用时才起作用的模块逻辑)。

其他提示

正确的做法是:

像创建任何类型的模块一样创建模块

只需创建您的 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.');
    }
}

如果我没猜错的话,通过 DI 在 CommandList 中定义的命令仅在已安装的 Magento 实例中可用,并且也仅适用于 Magento 模块(因为它们必须在 di.xml 中定义): https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/Console/Cli.php#L124

上述方法中的 Magento\Framework\App\DeploymentConfig::isAvailable() 检查 Config 中的安装日期以检查已安装的 Magento2: https://github.com/magento/magento2/blob/6352f8fbca2cbf21de88db0cf7f4555bfc60451c/lib/internal/Magento/Framework/App/DeploymentConfig.php#L83).

另一方面,Magento\Framework\Console\CommandLocator 中定义的命令始终可用,甚至可以由非 Magento 模块通过 Composer 自动加载的文件中的静态 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

所以我认为这两种方法都是需要的并且都有其存在的权利

许可以下: CC-BY-SA归因
scroll top