In Magento 2, the platform introduced a new command line interface called bin/magento
that is included in every installation. Most Magento developers are familiar with it because it makes it very easy to peform common tasks on the install like clear cache and install a database. What you might not know is that you can add custom commands to the Magento CLI to allow you to run your own code. I have used this feature to create custom cron jobs that can be executed by the OS cron instead of Magento’s cron system. Magento’s CLI is based on the Symfony Console package which is commonly used in the PHP ecosystem. Laravel bases their artisan
command on Symfony Console, for example. In Magento 2, you can create custom Symfony Console commands and include them in Magento’s CLI. To help other developers get started with console commands, I want to provide this quick tutorial.
I am assuming you have a Magento 2 installation ready to use for development. To learn how to set up Magento, check out Magento’s devdocs post for installation instructions. I used Magento Community 2.3.1 for this tutorial.
We need to create our own custom module in app/code
. I am calling my module Restoreddev_Console
. For every module we need a registration.php
and module.xml
file.
app/code/Restoreddev/Console/registration.php
<?php
use \Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Restoreddev_Console', __DIR__);
app/code/Restoreddev/Console/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="Restoreddev_Console" />
</config>
Now you can run php bin/magento setup:upgrade
to install your custom module into Magento’s database.
Next, we can create a class that implements Symfony Command that will be run when our command is executed. I want to create a custom command that clears the generated
directory, similar to how cache:flush
works. Add this class to your module:
app/code/Restoreddev/Console/Console/Command/GeneratedFlushCommand.php
<?php
namespace Restoreddev\Console\Console\Command;
use Symfony\Component\Console\Command\Command;
use Magento\Framework\Filesystem\DirectoryList;
use Magento\Framework\Filesystem\Io\File as FileIo;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class GeneratedFlushCommand extends Command
{
protected $fileIo;
protected $directoryList;
public function __construct(
FileIo $fileIo,
DirectoryList $directoryList
) {
parent::__construct();
$this->fileIo = $fileIo;
$this->directoryList = $directoryList;
}
protected function configure()
{
$this->setName('generated:flush');
$this->setDescription('Deletes code in generated folder');
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$path = $this->directoryList->getPath('generated');
$dirs = glob("$path/*", GLOB_ONLYDIR);
foreach ($dirs as $dir) {
$this->fileIo->rmdir($dir, $recursive = true);
}
$output->writeln('Generated folder successfully flushed');
}
}
There is a lot happening in this class, so we need to analyze it in sections.
Symfony\Component\Console\Command\Command
. The Symfony parent class provides the interface for our class to be included in the command list.__construct
method, we can inject Magento dependencies like other Magento classes. However, you do have to run parent::__construct();
for the class to be implemented properly.configure
method allows you to define the command name and description that appears in the CLI menu.execute
method contains the code that will run when the CLI command is executed. The method receives two objects: $input
(contains any console arguments) and $output
(allows you to send text to the terminal). I am using Magento’s classes to get the generated
directory and to delete any directories inside of it. At the end, I am using $output->writeln()
to send a success message to the user.Finally, we need to register the command in Magento’s dependency injection system. Create the following di.xml
file in your module.
app/code/Restoreddev/Console/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="generatedFlushCommand" xsi:type="object">Restoreddev\Console\Console\Command\GeneratedFlushCommand</item>
</argument>
</arguments>
</type>
</config>
In the di.xml
, we are targeting the CommandListInterface
and adding an additional command to its arguments. Now you can flush Magento’s cache (php bin/magento cache:flush
) and run php bin/magento
. You will see a new command called generated:flush
. If you execute it php bin/magento generated:flush
, then you will see all subdirectories in the generated
folder have been deleted.
I hope this quick tutorial has helped you learn about a neat new feature in Magento 2. If you would like to see another specific Magento tutorial, let me know on Twitter or on dev.to!