In this article, we will learn how to add a custom command line in console to perform Magento 2 functions.

These command lines are familiar with Magento developers when working with Magento, such as:

  • Installing/updating extensions
  • Clearing cache
  • Initiate Magento cron
  • ...

Before we start, you should know to create a simple module. In this article, we use a module called Magenest_CommandLine. Here are the steps to create a custom command line:

Step 1: Declare a custom command class in the file 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="exampleCommandLine" xsi:type="object">Magenest\CommandLine\Console\CustomCommand</item>
           </argument>
       </arguments>
   </type>
</config>

In this file, we declare a class CustomCommand to define command syntax and command action. Magento recommends putting command classes under [module root]/Command folder. Now let's create our CustomCommand class.

Step 2: Define command class

Magento 2 uses Symfony Console component for console commands, therefore we need to use several Symfony functions  in our class:

<?php

namespace Magenest\CommandLine\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 CustomCommand
* @package Magenest\CommandLine\Console
*/
class CustomCommand extends Command
{
   /**
    * Define command attributes such as name, description, arguments
    */
   protected function configure()
   {
       $this->setName('example:customcommand');
       $this->setDescription('Demo add custom command');
       parent::configure();
   }

   /**
    * method will run when the command is called via console
    * @param InputInterface $input
    * @param OutputInterface $output
    * @return int|void|null
    */
   protected function execute(InputInterface $input, OutputInterface $output)
   {
       $output->writeln("Welcome to Magenest!");
   }
}

Our class CustomCommand must extend core class Symfony\Component\Console\Command\Command. In this class, we need to declare 2 methods:

  • Configure() : define command attributes such as command syntax (method setName()), description (method setDescription()), parameter (use method setDefinition()).
  • Execute: define the executed action when this command is executed from Magento CLI. In this example, I printed a string “Welcome to Magenest!” to the terminal.

The necessary file and directory structure will look like the below image:

Magento 2 command line directory structure

After that, run the command php bin/magento setup:upgrade to install the module. To make sure that the command is declared, you can run the command php bin/magento list, which lists out all console commands:

all console commands

Now you can use the command php bin/magento example:customcommand, the result will look like this:

magento 2 add command line result

Adding parameters to command 

Many Magento console commands have parameters (required or optional) and here’s how we add parameters to command:

...
/**
* Class CustomCommand
* @package Magenest\CommandLine\Console
*/
class CustomCommand extends Command
{
   const NAME = 'name'; // key of parameter

   /**
    * Define command attributes such as name, description, arguments
    */
   protected function configure()
   {
       $options = [
           new InputOption(
               self::NAME, // the option name
               '-s', // the shortcut
               InputOption::VALUE_REQUIRED, // the option mode
               'Description for name parameter' // the description
           ),
       ];
       $this->setName('example:customcommand');
       $this->setDescription('Demo add custom command');
       $this->setDefinition($options);
       parent::configure();
   }

   /**
    * method will run when the command is called via console
    * @param InputInterface $input
    * @param OutputInterface $output
    * @return int|void|null
    */
   protected function execute(InputInterface $input, OutputInterface $output)
   {
       $name = $input->getOption(self::NAME);
       if ($name) {
           $output->writeln("Hi " . $name . ", Welcome to Magenest!");
       } else {
           $output->writeln("Welcome to Magenest!");
       }
   }
}

First, we define a new InputOption. It has some parameters including:

  • The option name
  • The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
  • The option mode: One of the VALUE_* constants. The modes include: NONE, REQUIRED, OPTIONAL and IS_ARRAY
  • A description text
  • The default value (must be null for if option mode is VALUE_NONE)

To add this InputOption to custom command, you use the setDefinition() method.

After that, you can see all params can use for this custom command by run php bin/magento example:customcommand --help, and the result will be:

Add custom command line in Magento 2: all params can use

After we’ve created the parameter, we need to capture them and using $input->getOption([name of option]) ($input->getOption(‘name’) in this case). In this simple example, we’ll add the name to output on the terminal.

Let’s try php bin/magento example:customcommand -s ”Doanh”  or php bin/magento example:customcommand --name=”Doanh”, here’s the result:

Add custom command line in Magento 2: php bin/magento example:customcommand -s ”Doanh”  or php bin/magento example:customcommand --name=”Doanh”

The finished Magenest/CommandLine module is provided at the end of this article.

How about doing more complex actions with console commands? With other Magento PHP classes, you can declare dependencies to command class’s constructor and use them inside execute() function. 

To expand further, you can dispatch Magento events inside the command class and have observer classes executed when the command is run. This behavior can be seen with cache commands. For example cache:clean command at vendor/magento/module-backend/Console/Command/CacheCleanCommand triggers adminhtml_cache_flush_system event.

Every module which creates Magento cache is expected to capture this event and clean their cache when the console command is run. 

Let us know if you want to discuss anything on "add custom command line in Magento 2" topic in the comment section below.