Create a custom command

Adobe Commerce and Magento Open Source enables your component to add commands to our Symfony-like command-line interface (CLI).

Commerce has one command-line interface that performs both installation and configuration tasks: <magento_root>/bin/magento. The new interface performs multiple tasks, including:

Other benefits:

Prerequisites

Before you begin, make sure you understand the following:

Add CLI commands using dependency injection

The sample modules provide a demonstration of many programming techniques, including adding a CLI command using dependency injection. Look at the sample-module-command for an example. The module's README.md discusses how to install it.

Following is a summary of the process:

  1. Create a Command class (the recommended location is <your component root dir>/Console/Command).

    See <Magento_Store_module_dir>/Console/Command/StoreListCommand.php for example.

    <?php
    
    declare(strict_types=1);
    
    namespace Magento\CommandExample\Console\Command;
    
    use Magento\Framework\Exception\LocalizedException;
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Input\InputOption;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class SomeCommand extends Command
    {
        private const NAME = 'name';
    
        protected function configure(): void
        {
            $this->setName('my:first:command');
            $this->setDescription('This is my first console command.');
            $this->addOption(
                self::NAME,
                null,
                InputOption::VALUE_REQUIRED,
                'Name'
            );
    
            parent::configure();
        }
    
        /**
         * Execute the command
         *
         * @param InputInterface $input
         * @param OutputInterface $output
         *
         * @return int
         */
         protected function execute(InputInterface $input, OutputInterface $output): int
         {
             $exitCode = 0;
             
             if ($name = $input->getOption(self::NAME)) {
                 $output->writeln('<info>Provided name is `' . $name . '`</info>');
             }
    
             $output->writeln('<info>Success message.</info>');
             $output->writeln('<comment>Some comment.</comment>');
    
             try {
                 if (rand(0, 1)) {
                    throw new LocalizedException(__('An error occurred.'));
                 }
             } catch (LocalizedException $e) {
                 $output->writeln(sprintf(
                     '<error>%s</error>',
                     $e->getMessage()
                 ));
                 $exitCode = 1;
             }
             
             return $exitCode;
         }
    }
    

    Style the output text by using <error>, <info>, or <comment> tags. See Symfony documentation for more information about styling.

  2. Declare your Command class in Magento\Framework\Console\CommandListInterface and configure the command name using dependency injection (<your component root dir>/etc/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\CommandListInterface">
            <arguments>
                <argument name="commands" xsi:type="array">
                    <item name="commandexample_somecommand" xsi:type="object">Magento\CommandExample\Console\Command\SomeCommand</item>
                </argument>
            </arguments>
        </type>
        ...
    </config>
    
  3. Clean the cache:

    bin/magento cache:clean
    
  4. Regenerate the code:

    bin/magento setup:di:compile
    

Result

As a result, the new command my:first:command that accepts a --name parameter is ready to use.

bin/magento my:first:command --name 'John'