The correct way is:
Create your module as you do for any kind of module
Just create your registration.php
file
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'My_Module',
__DIR__
);
And create you module.xml
file:
<?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>
Add an entry 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>
Create your command class:
<?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!');
}
}
To run your task just type:
php bin/magento my:command
About compatibility:
@api is not needed for commands, it is used for service contracts AFAIK.
If you need to let them compatible, just use an interface API inside your script instead of putting the logic inside it.
For example:
<?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.');
}
}