将 CLI 命令添加到 Magento 2 的正确且受支持的方法
题
是否有正确且官方支持的方法将 CLI 命令添加到 Magento 2 模块?根据我收集的信息,你的选择是
将您的命令类添加到
commands
的论证Magento\Framework\Console\CommandList
通过一个di.xml
文件通过注册您的命令
\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)
所以我认为这两种方法都是需要的并且都有其存在的权利