Magento 2: Add Custom Console CLI Command in your Module

Magento allows to create custom console commands to the Symfony-like command-line interface (CLI).

The Console component allows you to create command-line commands. You can create custom console commands for any task like import, export, or other batch jobs.

In this article, I will be creating a custom Magento2 module and will add a custom console command to it.

Create Custom Module & Add Custom Console Command

My custom module is named Chapagain_MyModule.

So, the module file path is app/code/Chapagain/MyModule.

app/code/Chapagain/MyModule/registration.php


<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Chapagain_MyModule',
    __DIR__
);

app/code/Chapagain/MyModule/etc/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="Chapagain_MyModule" setup_version="1.0.0">
    </module>
</config>

app/code/Chapagain/MyModule/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="myCustomCommand" xsi:type="object">Chapagain\MyModule\Console\MyCustomCommand</item>
           </argument>
       </arguments>
   </type>
</config>

app/code/Chapagain/MyModule/Console/MyCustomCommand.php


<?php

namespace Chapagain\MyModule\Console;

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 MyCustomCommand extends Command
{
   protected function configure()
   {
       $this->setName('chapagain:my-custom-command');
       $this->setDescription('My Custom Command Example');
       
       parent::configure();
   }

   protected function execute(InputInterface $input, OutputInterface $output)
   {
       $output->writeln("Hello from Mukesh Chapagain!");
   }
}

Enable the module and clear cache


bin/magento module:enable Chapagain_MyModule
bin/magento cache:flush

List all the commands


bin/magento list

You should see your newly added command in the list.


chapagain
  chapagain:my-custom-command                  My Custom Command Example

Execute the command


bin/magento chapagain:my-custom-command
Hello from Mukesh Chapagain!

Print the manual of the custom command


bin/magento chapagain:my-custom-command --help

Description:
  My Custom Command Example

Usage:
  chapagain:my-custom-command

Options:
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Add Parameters Options to the Console Command

  • Options are not ordered (meaning you can specify them in any order)
  • Options are specified with two dashes (e.g. --yell).
  • Options are always optional
  • Options can be setup to accept a value (e.g. --dir=src) or as a boolean flag without a value (e.g. --yell).

You can add multiple required or optional parameters to your custom console command.

We will be updating the class Chapagain\MyModule\Console\MyCustomCommand.

app/code/Chapagain/MyModule/Console/MyCustomCommand.php


<?php

namespace Chapagain\MyModule\Console;

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 MyCustomCommand extends Command
{
    private const YOUR_NAME = 'name';

    protected function configure()
    {
        $this->setName('chapagain:my-custom-command');
        $this->setDescription('My Custom Command Example');
        $this->addOption(
            // this is the name that users must type to pass this option (e.g. --iterations=5)
            self::YOUR_NAME,
            // this is the optional shortcut of the option name, which usually is just a letter
            // (e.g. `i`, so users pass it as `-i`); use it for commonly used options
            // or options with long names
            null,
            // this is the type of option (e.g. requires a value, can be passed more than once, etc.)
            InputOption::VALUE_REQUIRED,
            // the option description displayed when showing the command help
            'My Description of the parameter'
            // last parameter not used here
            // last parameter is the default value of the option (for those which allow to pass values)
        );
        
        parent::configure();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $name = $input->getOption(self::YOUR_NAME);
        if ($name) {
            $output->writeln("Hi " . $name . ", Welcome from Chapagain!");
        } else {
            $output->writeln("Hello from Mukesh Chapagain!");
        }
    }
}

There are five option variants you can use:


InputOption::VALUE_IS_ARRAY
This option accepts multiple values (e.g. --dir=/foo --dir=/bar);

InputOption::VALUE_NONE
Do not accept input for this option (e.g. --yell). The value returned from is a boolean (false if the option is not provided). This is the default behavior of options;

InputOption::VALUE_REQUIRED
This value is required (e.g. --iterations=5 or -i5), the option itself is still optional;

InputOption::VALUE_OPTIONAL
This option may or may not have a value (e.g. --yell or --yell=loud).

InputOption::VALUE_NEGATABLE
Accept either the flag (e.g. --yell) or its negation (e.g. --no-yell).

Read more: Console Input (Arguments & Options)

Test the console command options

bin/magento chapagain:my-custom-command --help

Description:
  My Custom Command Example

Usage:
  chapagain:my-custom-command [options]

Options:
      --name=NAME       My Description of the parameter
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Execute the command with & without options

bin/magento chapagain:my-custom-command
Hello from Mukesh Chapagain!

bin/magento chapagain:my-custom-command --name

  The "--name" option requires a value.

chapagain:my-custom-command [--name NAME]

bin/magento chapagain:my-custom-command --name Sam
Hi Sam, Welcome from Chapagain!

bin/magento chapagain:my-custom-command --name=Sam
Hi Sam, Welcome from Chapagain!

Hope this helps. Thanks.