Drupal Console: The Drupal Developer’s Swiss Army knife

Author picture
Gareth Goodwin profile
Posted by
Gareth Goodwin

Ok, so the first time I used Drupal Console, I sent out the following tweet:

I’ve been using it again a bit more recently, now that we’re doing more & more Drupal 8, and since last time it’s even better.

Whilst the changes in Drupal 7 to Drupal 8 behind the scenes have been vast, I’ve had a much easier time onboarding with it & starting to develop straight away thanks to Drupal Console. I also believe it’s helping me deliver better functionality, as the amount of time I’m saving means I can implement the ‘nice-to-haves’ that as a developer I want to do, but clients don’t want to pay for!

What is Drupal Console?

“The new CLI for Drupal. A tool to generate boilerplate code, interact with and debug Drupal”

If you’ve been using Drupal, I’m sure you’ll be familiar with Drush - Drupal Console is another CLI tool, but contains a lot of features that make a developer’s life much easier. It allows you to generate code, debug issues & interact with Drupal.

What can it do?

For interacting with Drupal, you’ve got commands like cache:rebuild, config:import, module:install and user:password:reset. These are similar to Drush commands.

For debugging, there’s commands that list various parts of the system like plugin:debug, config:debug and libraries:debug.

But the best thing about it (from a developer's perspective) is the ability to generate code & components, which is where I’m using Drupal Console the most. Commands such as generate:module, generate:service, generate:controller mean you can create a module & a custom page without writing a single line of code - all you need to do is answer a few questions.

How do you use it?

Once you’ve installed it, it’s as simple as typing:

drupal [command]

It will then ask you for any information it needs in order to complete that command. You can provide this information as arguments to the command, so for example drupal cache:rebuild [arguments] could be provided as drupal cache:rebuild discovery to clear the discovery cache.

For some of the information it asks you for, it will have a default value that it will use if you don’t provide one. This is provided at the end of what it asks for, inside []. Simply press return to accept the default, or type the information to override the default.

Example module

How am I using it?

I’m using it mainly to rapidly set up & prototype functionality when building new features for our Drupal 8 installs. My favourite commands so far, are:

drupal generate:module

This command allows you to create a brand new Drupal module, by just answering a few questions. At a bare minimum, you just need to give the module a name (though you’ll probably want to add the description too) and it will do the rest for you using sensible defaults. That’s it. You’re now able to enable the module, open the .module file & start writing code or use Drupal Console to add more to it.


drupal generate:controller

To create a custom page/path in Drupal 8, you need to declare a route. This route calls a controller, which is a PHP Class. To generate this manually, you’d need to create a modulename.routing.yml file, provide the information about the route (the path, the requirements, the controller class), then generate the controller class file + PHP class itself.

With the generate:controller command, you tell it which module to add the controller to, what controller class to generate, what method on the controller to call, what the path for the route is and if you want to load any services from the container. In the example below, I’ve added an route at /example-page, that will require the config.factory & http_client services.

This means I haven’t had to worry about the syntax for the routing.yml file, the PSR namespacing for the controller PHP class file, using dependency injection to require the services the controller needs. All I have to do is open the file containing the class it created, and update the method I chose to return the page content.

Important note: The one thing it doesn’t ask for is the permission or access callback for the generated route, so you will need to edit the routing.yml file to set this if it’s anything other than ‘access content’. If you need to create a new permission, try out the generate:permissions command!


drupal generate:form:config

Ok, this one is my current favourite (don’t tell the others!). This command will generate a page/form for you that manages Drupal site configuration. Drupal 8 brought with it the brilliant Configuration Management functionality, which makes it much easier for creating & managing configuration such as content types, fields and site information. Using the drupal generate:form:config command allows you to provide a form for site administrators to manage settings that may vary per site - for example API login details or messages displayed around the site.

It even allows you to define the form structure, so you can define fields & set their labels, descriptions and default values. By doing this, it also generates the submit function for the form with the code needed to save those field values as configuration.

We currently maintain a set of very similar websites for a client, that are all based on the same codebase. This command has allowed me to give the client more control over custom functionality and importantly allow settings specific to each site, which in the Drupal 6 version were hardcoded for budget reasons. Whilst there was the system_settings_form in Drupal 7 to help with this, it wasn’t as easy as Drupal Console makes it in Drupal 8.


How is it helping me ship better sites?

In my latest tweet, I claimed it’s helping us ship better sites. That’s quite a bold claim, but I believe it’s true.

It’s allowing me to prototype & try out ways of doing things quickly - generating modules, controllers, forms & config means I can spend my time trying things out & validating ideas, rather than setting things up manually, looking up the right functions & syntax. If the thing I’m prototyping is right, then the code it’s generated is instantly usable as opposed to the @todo ridden code with hardcoded values that is usually generated by rapid prototyping. This rapid prototyping means I can spend more time on developing something once I know it’s right, rather than losing time to trying out several ideas.

But more importantly, it means I can do much more than I would be able to without it. As a developer, I often think ‘Hey, we could do this by just doing the basics, but the best way to do this would be to have a config screen for this, a service for that, a controller over here…’, but client budgets or timescales often dictate that’s not possible. Being able to generate the modules, services, controllers & forms means I can do things the best way possible, I can do more than usual without blowing the project budget.

And with learning Drupal 8?

I mentioned at the start it’s helped me with the onboarding process with Drupal 8. By generating a controller for example, I’m able to open up the resulting files & take a look at what routing it generated, how it’s handled dependency injection, made use of services & so on along with seeing what changes when I choose different options. The parts it generates that I don’t recognise or are new to Drupal 8 I’ve been able to pinpoint what I need to read up on.

What about Drush? Does this replace it?

So far, it’s not replaced drush for me. We’ve been using drush for over 6 years here at Five Mile, so it’s on all of our servers, all of our local development environments & it’s embedded in our workflow. It’s not going away that easily.

But I could see it going that way in the future - the commands for interacting with Drupal in the way Drush does are all making it into Drupal Console, so as we use Drupal 8 more & more Drupal Console could take centre stage.

About Gareth Goodwin:

I joined Five Mile in 2010 and I am Lead Drupal Developer. My other expertise is in: PHP, MySQL, JavaScript developer, technical architect, test developer, server administration.


[Note: At the time of writing, I was using Drupal Console version 1.0.0-beta4.]