---
url: 'https://metadrop.net/en/arcicles/creating-command-using-drupal-console'
title: 'Creating a command using Drupal Console'
author: 'Eduardo Morales'
date: '2018-06-22T11:18:09+00:00'
updated: '2026-06-10T07:51:33+00:00'
type: article
summary: 'How to create Drupal Console commands, a tool for Drupal 8 that allows us to make certain development tasks easier.'
tags:
  - 'Drupal Planet'
published: true
og:
  determiner: Automatic
  site_name: Metadrop
  'image:alt': 'Creating a command using Drupal Console'
  street_address: 'Calle Manuel Luna, 12, 3 Dcha'
  locality: Madrid
  region: Madrid
  postal_code: '28020'
  country_name: España
  email: hola@metadrop.net
  phone_number: '910053180'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      '@type': Article
      '@id': 'https://metadrop.net/en/arcicles/creating-command-using-drupal-console#article'
      name: 'Creating a command using Drupal Console'
      headline: 'Creating a command using Drupal Console'
      description: 'How to create Drupal Console commands, a tool for Drupal 8 that allows us to make certain development tasks easier.'
      datePublished: '2019-12-13T13:18:09+0100'
      dateModified: '2026-06-10T09:51:33+0200'
      author:
        '@type': Person
        name: 'Eduardo Morales'
      publisher:
        '@type': Organization
        '@id': 'https://metadrop.net/#organization'
      mainEntityOfPage: 'https://metadrop.net/en/arcicles/creating-command-using-drupal-console'
    -
      '@type': Organization
      '@id': 'https://metadrop.net/#organization'
      url: 'https://metadrop.net/'
      name: Metadrop
      sameAs:
        - 'https://www.drupal.org/metadrop'
        - 'https://twitter.com/metadrop'
        - 'https://asociaciondrupal.es/partner/metadrop'
        - 'https://www.linkedin.com/company/metadrop'
      logo:
        '@type': ImageObject
        url: 'https://metadrop.net/themes/custom/mdrop_radix/logo-metadrop-500-500.jpg'
        width: '500'
        height: '500'
    -
      '@type': ItemPage
      '@id': 'https://metadrop.net/en/arcicles/creating-command-using-drupal-console'
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Home
            item: 'https://metadrop.net/en'
      publisher:
        '@type': Organization
        '@id': 'https://metadrop.net/#organization'
---
# Creating a command using Drupal Console

Friday, December 13, 2019

 

 



How to create Drupal Console commands, a tool for Drupal 8 that allows us to make certain development tasks easier.



   



## Introduction

[Drupal Console](https://drupalconsole.com/ "Web de Drupal Console") eases Drupal 8 development in different ways, but the one we're interested in in in this article is code generation. In version 8 Drupal has become much more object-oriented, which is good, but in return it is more complex to do certain tasks that were previously done by implementing one or two hooks in the .module file. This is where Drupal Console comes in: it offers commands to generate code for many of the tasks you may need to develop.

Some examples of commands:

```plaintext
drupal generate:module [options] # Generates base code for a new module.
drupal generate:service [options] # Generates base code for a service.
drupal generate:form [options] # Generates base code for a form.
```

In this way you can generate code with the base for a new module, a new form (you can even tell him what form elements you want!) or a new Drupal service.

But in this article we will not talk about generating code, but create a new Drupal Console command for Drupal 8. Specifically, in this practical example we are going to create a Drupal Console command that will allow us to generate the code base for a QueueWorker. A QueueWorker is in charge of processing the elements of a Drupal 8 queue API queue. Let's imagine that our web requires to make a process on certain data, for example on data that are received from time to time from external sources. By means of the [Queue API](https://api.drupal.org/api/drupal/core!core.api.php/group/queue/8.2.x "Queue API at Drupal.org") we can create a queue, insert the received data in this queue, and that later a QueueWorker would recover and process the data.

## Drupal Console installation

First you'll need to install Drupal Console. As many (if not all) Drupal projects, we use [Composer](https://getcomposer.org/ "Composer home page") to add it as a dependency.

```bash
composer require drupal/console:~1.0 \
--prefer-dist \
--optimize-autoloader
```

You can install Drupal Console Launcher to execute Drupal Console globally without using the complete path (*vendor/bin/drupal*) on each project. Check the [documentation](https://docs.drupalconsole.com/en/getting/project.html "Getting the project").

## Create a scaffolding for a command

To create our own Drupal Console command what better way to start than by using Drupal Console to generate the initial code. This is what is called scaffolding: the action of generating the code and directories needed to start a project or component.

Therefore we will use the following command:

```bash
drupal generate:command [options]
```

The command's options are:

```bash
--extension=EXTENSION   Extension name
--extension-type=EXTENSION-TYPE  Extension type (module, theme, profile).
--class=CLASS   The class that defines the commands (it should end on 'Command').
--name=NAME   The name of the command.
--initialize   Adds an initialize method.
--interact   Adds an interact command, in charge of processing input params.
--container-aware   Check a Drupal site is installed.
--services[=SERVICES]   Adds services.
--generator   Adds a Generator class in charge of handling the scaffolding.
```

Options are not mandatory, if not provided Drupal Console asks for them when run.

In this case we want to generate a command in the 'drupal\_console\_queue' extension of type module. We'll use a class called PluginQueueWorkerCommand, and the command will be *generate:plugin:queue*. The command line would be:

```plaintext
drupal generate:command  \
  --extension="drupal_console_queue"  \
  --extension-type="module"  \
  --class="PluginQueueWorkerCommand"  \
  --name="generate:plugin:queue" \
  --generator \
  --interact \
  --container-aware
```

This will generate a bunch of files and directories with the base for the command. Something like this:

Let's check the generated module files according to their importance.

The main class is PluginQueueWorkerCommand, as it will be in charge of registering the Drupal command, that is, informing Drupal Console of the existence of a custom command. It will be located inside the */src/Command/Generate* folder as it is a code generation command. This class extends Drupal\\Console\\Annotations\\DrupalCommand and has an annotation to register it in Drupal Console, besides importing *Drupal\\Console\\Annotations\\DrupalCommand* through the PHP use clause.

The generated code will be something like this:

```php
namespace Drupal\drupal_console_queue\Command\Generate;

use Drupal\Console\Annotations\DrupalCommand;

/**
 * Class PluginQueueWorkerCommand.
 *
 * @DrupalCommand (
 *     extension="drupal_console_queue",
 *     extensionType="module"
 * )
 */
class PluginQueueWorkerCommand extends ContainerAwareCommand {
```

To inject services we need to create a *console.services.yml* file in module root directory. Here's an example to inject some services in the command class and the generator class.

```php
services:
  drupal_console_queue.generate_queue:
    class: Drupal\drupal_console_queue\Command\Generate\PluginQueueWorkerCommand
    arguments: ['@drupal_console_queue.plugin_queue_generator','@console.validator','@console.string_converter','@console.chain_queue']
    tags:
      - { name: drupal.command }
  drupal_console_queue.plugin_queue_generator:
    class: Drupal\drupal_console_queue\Generator\PluginQueueWorkerGenerator
    arguments: ['@console.extension_manager']
    tags:
      - { name: drupal.generator }

```

Back to the PluginQueueWorkerCommand class, we'll define the injected services in the class **constructor**. In this case, we inject the generator that's in charge of generating the scaffolding code, the validator that helps to validate the user input, and the stringConverter to deal with the text.

```php
...
   * @param \Drupal\Console\Core\Utils\ChainQueue $chainQueue
   *   Chain queue.
   */
  public function __construct(
    GeneratorInterface $queue_generator,
    Validator $validator,
    StringConverter $stringConverter
  ) {
    $this->generator = $queue_generator;
    $this->validator = $validator;
    $this->stringConverter = $stringConverter;
    parent::__construct();
  }
```

The **configure** method provides an alias to the Drupal Console command and add the available options.

```php
  /**
   * {@inheritdoc}
   */
  protected function configure() {
    $this
      ->setName('generate:plugin:queue')
      ->setDescription($this->trans('commands.generate.plugin.queue.description'))
      ->setHelp($this->trans('commands.generate.plugin.queue.help'))
      ->addOption(
          'module',
          NULL,
          InputOption::VALUE_REQUIRED,
          $this->trans('commands.generate.plugin.queue.options.module')
      )
...
          'label',
          NULL,
          InputOption::VALUE_REQUIRED,
          $this->trans('commands.generate.plugin.queue.options.label')
      )
      ->setAliases(['gpqueue']);
  }
```

The command name can be added with the **setName** method.

Each option of the command is added with **addOption** method, its arguments are the argument name, an optional shortcut, input type (VALUE\_NONE, VALUE\_REQUIRED, VALUE\_OPTIONAL, VALUE\_IS\_ARRAY) and the last argument corresponds to the help description for the command.

You can type the text directly, but if you want the command to be available in several languages you should use the **trans** method using *commands.filename.option* as an argument and add the translation yml file inside the folder *drupal\_console\_queue/console/translations/&lt;language&gt;* (in/en/fr...) with the translation.

For example, for this module we have the [generate.plugin.queue.yml](https://github.com/Eduardomoberti/drupal_console_queue/blob/8.x-1.x/console/translations/en/generate.plugin.queue.yml) file placed in *drupal\_console\_queue/console/translations/en*.

```plaintext
description: 'Drupal Console Queueworker generator.'
help: 'The <info>generate:plugin:queue</info> command helps you generate a new queue worker plugin.'
welcome: 'Welcome to the Drupal Queue Worker Plugin generator'
options:
  module: 'The module name'
...
```

Also, using the **setAliases** method we can define an alias for the Drupal Console command. The parameter is an array so more than one can be defined.

On the other hand you can create the interact method where you process each argument when launching the command. If your command does not need to interact with the user, this method is not needed.

```php
  /**
   * {@inheritdoc}
   */
  protected function interact(InputInterface $input, OutputInterface $output) {
    // --module option.
    $this->getModuleOption();

    // --class option.
    $queue_class = $input->getOption('class');
    if (!$queue_class) {
      $queue_class = $this->getIo()->ask(
            $this->trans('commands.generate.plugin.queue.questions.class'),
            'ExampleQueue',
            function ($queue_class) {
              return $this->validator->validateClassName($queue_class);
            }
        );
      $input->setOption('class', $queue_class);
    }
...
```

In the example shown above we get the option class, and if it's not defined (because the user has not provided any options when executing the command), then we ask the users using the console with the **ask** method. The arguments of the ask method are the question that will be asked to the user (if we use the trans method and we have to define the translation in the yml file mentioned previously), the default value, and an input validation function that must be a callable (a function).

Once we get the answer from the user, we process it as needed. The option is defined with the value obtained with the **setOption** method, being the first argument the name of the option and the second argument the value of the option.

The last and most important method is the **execute** method. It is the method that actually performs the command actions.

```php

  /**
   * {@inheritdoc}
   */
  protected function execute(InputInterface $input, OutputInterface $output) {
    // @see use Drupal\Console\Command\Shared\ConfirmationTrait::confirmOperation
    if (!$this->confirmOperation()) {
      return 1;
    }
    $module = $input->getOption('module');
...
    $this->generator->generate([
      'module' => $module,
...
    ]);


    return 0;
  }
```

In our case we want to generate the scaffolding for a **QueueWorker**, so we pass the arguments from the command to the generator.

Let's now check the class in charge og generating the scaffolding code, the [PluginQueueWorkerGenerator](https://github.com/Eduardomoberti/drupal_console_queue/blob/8.x-1.x/src/Generator/PluginQueueWorkerGenerator.php "PluginQueueWorkerGenerator") class. It's located inside the *src/Generator* folder. ​

This class should extend Drupal\\Console\\Core\\Generator\\Generator and implement the Drupal\\Console\\Core\\Generator\\GeneratorInterface. It should be part of the Drupal\\Console\\Generator package as well.

```php
<?php

namespace Drupal\drupal_console_queue\Generator;

use Drupal\Console\Core\Generator\Generator;
use Drupal\Console\Core\Generator\GeneratorInterface;
use Drupal\Console\Extension\Manager;

/**
 * Class QueueWorkerGenerator.
 *
 * @package Drupal\Console\Generator
 */
class PluginQueueWorkerGenerator extends Generator implements GeneratorInterface {
```

As we did in the commands class, if we have defined some service in the *console.services.yml* file we must define it in the constructor. In this case we have injected the extension manager.

```php
  /**
   * Extension Manager.
   *
   * @var \Drupal\Console\Extension\Manager
   */
  protected $extensionManager;

  /**
   * PluginQueueWorker constructor.
   *
   * @param \Drupal\Console\Extension\Manager $extensionManager
   *   Extension manager.
   */
  public function __construct(
       Manager $extensionManager
   ) {
    $this->extensionManager = $extensionManager;
  }

```

The only method that the interface forces us to implement is the generate method, which is in charge of generating the scaffolding code.

In this case we get the options of the module where we want to generate the scaffolding code and the name of the class for the QueueWorker.

```php
  /**
   * {@inheritdoc}
   */
  public function generate(array $parameters) {
    $module = $parameters['module'];
    $queue_class = $parameters['class_name'];
...
```

Later we define the directory where the template is with *$this-&gt;renderer-&gt;addSkeletonDir.* It needs the template twig location as parameter since the generation of scaffolding is done using a twig template.

The next step is to generate the file with the *method $this-&gt;renderFile*. The first argument is the path relative to the template folder. The second argument is file path and name of the generated file. Using the Extension Manager we get module path where the plugins should be located. The last argument will be the variables we want to use in twig.

```plaintext
...
    $this->renderer->addSkeletonDir(__DIR__ . '/../../console/templates');
    $this->renderFile(
      'module/src/Plugin/QueueWorker/queue_worker.php.twig',
      $this->extensionManager->getPluginPath($module, 'QueueWorker') . '/' . $queue_class . '.php',
      $parameters
    );
  }
```

We create the twig in the [drupal\_console\_queue/console/templates/module/src/Plugin/QueueWorker/queue\_worker.php](https://github.com/Eduardomoberti/drupal_console_queue/blob/8.x-1.x/console/templates/module/src/Plugin/QueueWorker/queue_worker.php.twig "Template twig queueworker.") file.

And it's ready! This is you need to create a Drupal Console command the creates a QueueWorker plugin. From this you can create other Drupal Console generator command or adapt this example to the code you want to generate.

This example has been contributed to the Drupal Console, here you can check the Pull Requests and see all the needed code. They are already commited to Drupal Console :)

[Pull request for the Drupal Console QueueWorker Generator.](https://github.com/hechoendrupal/drupal-console/pull/3950 "Pull request Drupal Console QueueWorker Generator.")

[Pull requestfor the Drupal Console QueueWorker Generator](https://github.com/hechoendrupal/drupal-console-en/pull/215 "Pull request traducción Drupal Console QueueWorker Generator.") translation.

## **Related links**

[Install Drupal Console.](https://docs.drupalconsole.com/en/getting/project.html "Instalar Drupal Console.")

[Create a custom Drupal Console command.](https://docs.drupalconsole.com/en/extending/creating-custom-commands.html "Crear un comando custom con Drupal Console.")

[Repository with the code of this article](https://github.com/Eduardomoberti/drupal_console_queue "Drupal console queue").



- Eduardo Morales
    
    Senior Drupal developer
 
[Module development and third-party integrations with Drupal](https://metadrop.net/en/services/drupal/integrations " See Module development and third-party integrations with Drupal")

Metadrop connects Drupal to your CRM, ERP, payment, and marketing stack — Salesforce, Microsoft Dynamics, BBVA virtual POS, Workday, and Keepeek — with custom modules and secure, GDPR-compliant APIs.

 

 See more