This is a beta release of documentation for Magento 2.4, published for previewing soon-to-be-released functionality. Content in this version is subject to change. Links to the v2.4 code base may not properly resolve until the code is officially released.

How to add CLI commands

Overview of adding CLI commands

Magento enables your component to add commands to our Symfony-like command-line interface (CLI).

About the Magento CLI

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

  • Installing Magento (and related tasks such as creating or updating the database schema, creating the deployment configuration, and so on).
  • Clearing the cache.
  • Managing indexes, including reindexing.
  • Creating translation dictionaries and translation packages.
  • Generating non-existent classes such as factories and interceptors for plug-ins, generating the dependency injection configuration for the object manager.
  • Deploying static view files.
  • Creating CSS from Less.

Other benefits:

  • A single command (<magento_root>/bin/magento list) lists all available installation and configuration commands.
  • Consistent user interface based on Symfony.
  • The CLI is extensible so third party developers can “plug in” to it. This has the additional benefit of eliminating users’ learning curve.
  • Commands for disabled modules do not display.

Prerequisites

Before you begin, make sure you understand the following:

  • All Magento command-line interface (CLI) commands rely on the Magento application and must have access to its context, dependency injections, plug-ins, and so on.
  • All CLI commands should be implemented in the scope of your module and should depend on the module’s status.
  • Your command can use the Object Manager and Magento dependency injection features; for example, it can use constructor dependency injection.
  • Your command should have an unique name, defined in the configure() method of the Command class:

    1
    2
    3
    4
    5
    6
    7
    8
    
    protected function configure()
    {
       $this->setName('my:first:command');
       $this->setDescription('This is my first console command.');
    
       parent::configure();
    }
    ...
    

    or in the di.xml file:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
       ...
       <type name="Magento\CommandExample\Console\Command\SomeCommand">
          <arguments>
             <!-- configure the command name via constructor $name argument -->
             <argument name="name" xsi:type="string">my:first:command</argument>
          </arguments>
       </type>
       ...
    </config>
    

    or in the __construct method (declaration is similar to di.xml):

    1
    2
    3
    4
    
    public function __construct()
    {
        parent::__construct('my:first:command');
    }
    

    Otherwise the Symfony framework will return an The command defined in "<Command class>" cannot have an empty name. error.

Add CLI commands using dependency injection

The Magento 2 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.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
    <?php
        namespace Magento\CommandExample\Console\Command;
    
        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
         */
        class SomeCommand extends Command
        {
            const NAME = 'name';
    
            /**
             * @inheritDoc
             */
            protected function configure()
            {
                $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 null|int
             */
            protected function execute(InputInterface $input, OutputInterface $output)
            {
                if ($name = $input->getOption(self::NAME)) {
                    $output->writeln('<info>Provided name is `' . $name . '`</info>');
                }
    
                $output->writeln('<info>Success Message.</info>');
                $output->writeln('<error>An error encountered.</error>');
                $output->writeln('<comment>Some Comment.</comment>');
            }
        }
    

    Style the output text by using <error>, <info>, or <comment> tags. See Symfony docummentation 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):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    <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:

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

    1
    
    bin/magento setup:di:compile
    

Result

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

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

Related topic

Command naming guidelines