April 5, 2023

Drush 11 generate command examples

Speed up module & theme development with these handy Drush commands

Fed up with writing module & theme code? Wish there was a way to get the module structure & files in-place before you start your custom coding? Well I recently found a bunch of useful Drush 11 commands that will streamline your module & theme development, here's some examples of Drush generate commands

What is Drush?

Drush (combo of Drupal + Shell) is a command line tool used to control your Drupal installation(s) with. With Drush you can easily running database updates, clear caches, log in, export/import configurations and more all by typing a few commands into your Terminal.

If you don't already use Drush well in short once you try it you'll probably wonder how you ever lived without it. In addition, if your building Drupal projects with Composer (which you really should) it's very simple to install Drush both on your local machine and on your live servers.


Installing Drush with Composer

You can install Drush both global (your whole machine) and at project level (ie. within your Drupal site directory) as a vendor package.

Global used to be the way to go but now with Drupal embracing Composer it's very easy to install Drush with Composer and use it as a vendor package specific to the Drupal project.
This has a big advantage over a global install: Composer will find the right Drush version for your version of Drupal so you don't have to, if you install Drush globally you might end up with 1 Drupal site needing say Drush 9 and 1 Drupal needing Drush 11 so for me installing Drush with Composer is the only sustainable option. It also means you'll have Drush available at project level on your servers too once you deploy your Drupal site.

To install Drush with Composer running:

composer require drush/drush (prefix with ddev if you're running DDEV)

Inspect your composer.json file and you should now see if new line in require: "drush/drush": "^11.5",

Now to run Drush at project level, open Terminal/Command line and go to the directory when your composer.json file is and you can run (use this locally or on live servers):

vendor/drush/drush/drush DRUSH-COMMAND
OR
vendor/bin/drush DRUSH-COMMAND

If you're working locally and use DDEV you can just run: ddev drush DRUSH-COMMAND

Run the drush status command to ensure everything is working and you should see something like the following output:

Drupal version   : 10.0.7                                     
Site URI         : https://SITE.ddev.site                 
DB driver        : mysql                                      
DB hostname      : db                                         
DB port          : 3306                                       
DB username      : db                                         
DB name          : db                                         
Database         : Connected                                  
Drupal bootstrap : Successful                                 
Default theme    : olivero                                    
Admin theme      : claro                                      
PHP binary       : /PHP-BINARY-PATH/php8.1                            
PHP config       : /PHP-PATH/php/8.1/cli/php.ini                   
PHP OS           : Linux                                      
PHP version      : 8.1.8                                      
Drush script     : /PROJECT-PATH/vendor/bin/drush             
Drush version    : 11.5.1                                     
Drush temp       : /tmp                                       
Drush configs    : /PROJECT-PATH/vendor/drush/drush/drush.yml 
Install profile  : standard                                   
Drupal root      : /PROJECT-PATH/.                            
Site path        : sites/default                              
Files, Public    : sites/default/files                        
Files, Temp      : /tmp 

Pretty easy right?!


Drush 11 generate commands

Drush generate commands were added to Drush 11 and I believe similar functionality used to be available in Drupal Console called scaffolding, with Drupal Console seemingly now abandoned Drush took over the reins and added it's own set of really awesome generate commands.

Generate commands basically build you the file structure for all types of code within Drupal, be that a complete new module or a new custom service or custom permissions or even a Javascript file, run a few commands and Drush will create the files & structure you need and even ask you about dependency injection you might need.

The basic command is: drush generate THING-TO-GENERATE


Drush 11 generate command examples

I've picked out 4 examples of Drush generate commands that I regularly use. I'll use the DDEV command version since all these commands are for while you're site is in active development which should only be done locally.

1) drush generate module

I use this every time I need to build a new custom module on projects, it creates the module directory & files you select based on the options all named for the module and ready to start coding with.

For this example we'll make a basic new module called "drush_generate_demo" by running:

ddev drush generate module

First thing with all commands that Drush will ask for is the module name ie. "Drush Generate Demo" then the machine name which it will autosuggest for you based on the module name. Then you can add a description and package.

Next you'll be asked about dependencies you module has in order to function. For the sake of this example type: drupal:search, drupal:shortcut and add the Core Search & Shortcut modules as requirements for our module.

You'll then get a selection of questions based on what files you want to add to your module, this is dependant on the module you're making, you can always come back and add new files with other generate commands, I've add a module, install & libraries.yml file for this example.

Welcome to module generator!
––––––––––––––––––––––––––––––

 Module name [Html]:
 ➤ Drush Generate Demo

 Module machine name [drush_generate_demo]:
 ➤ 

 Module description [Provides additional functionality for the site.]:
 ➤ 

 Package [Custom]:
 ➤ 

 Dependencies (comma separated):
 ➤ drupal:search,drupal:shortcut             

 Would you like to create module file? [No]:
 ➤ Yes

 Would you like to create install file? [No]:
 ➤ Yes

 Would you like to create libraries.yml file? [No]:
 ➤ Yes

 Would you like to create permissions.yml file? [No]:
 ➤ 

 Would you like to create event subscriber? [No]:
 ➤ 

 Would you like to create block plugin? [No]:
 ➤ 

 Would you like to create a controller? [No]:
 ➤ 

 Would you like to create settings form? [No]:
 ➤ 

 The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.info.yml
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.install
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.libraries.yml
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.module

And there you see Drush has created a bunch of new module files automatically for us, nice!!

2) drush generate hook

Next we want to add a HOOK_form_alter hook to our module, it's as simple as:

ddev drush generate hook

For "Module machine name" if you've installed the "drush_generate_demo" module when you start to type "drush_generate_demo" and Drush will autocomplete and find the module name.

Now for "Hook name" start writing the name of the hook ie. form_alter and again Drush will autocomplete. Resulting in:

 Welcome to hook generator!
––––––––––––––––––––––––––––

 Module machine name [html]:
 ➤ drush_generate_demo

 Hook name:
 ➤ form_alter

 The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.module

Open up drush_generate_demo.module and you'll see the new form_alter hook commented and filled with example code:

drush generate hook example
drush generate hook example result

3) drush generate service:custom

Ok so let's pretend we've started to build out our module with lots of repeated custom code and it's starting to get messy, in cases like this I like to create a custom "helper" service which I can call on and store repetitive functions in to use throughout my module code.

Run:

ddev drush generate service:custom

And answer the following:

Welcome to custom-service generator!
––––––––––––––––––––––––––––––––––––––

 Module machine name [html]:
 ➤ drush_generate_demo

 Service name [drush_generate_demo.example]:
 ➤ drush_generate_demo.helpers

 Class [Helpers]:
 ➤ DrushGenerateDemoHelpers

 Would you like to inject dependencies? [Yes]:
 ➤ 

 Type the service name or use arrows up/down. Press enter to continue:
 ➤ entity_type.manager

 Type the service name or use arrows up/down. Press enter to continue:
 ➤ 

 The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.services.yml
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/src/DrushGenerateDemoHelpers.php

I've injected entity_type.manager as an example so we it's available to lookup content using the getStorage() method.

You can now call the service like so:

$helpers = \Drupal::service('drush_generate_demo.helpers');
$helpers->someFunctionInCustomService();

Or you can inject it which we'll let Drush do for us in the next example.

4) drush generate controller

Next let's add a page using a controller to our module by running:

ddev drush generate controller

Use the same Module machine name as before and accept the default Class name then here's the bit I really like, you can tell Drush which service dependencies to inject into your controller to make use of.

For our example let's inject our custom service from above along with @logger.factory so we could write logs to the database & @config.factory so we can read configurations stored in Drupal. Say yes to "Would you like to inject dependencies? [No]:" and then in "Type the service name (without the @ sign) or use arrows up/down. Press enter to continue:" start typing the name of the service you want to add or you can scroll up and down with the arrow keys.

Next select "Yes" for "Would you like to create a route for this controller? [Yes]:" and use the defaults for the remaining questions:

 Welcome to controller generator!
––––––––––––––––––––––––––––––––––

 Module machine name [html]:
 ➤ drush_generate_demo

 Class [DrushGenerateDemoController]:
 ➤ 

 Would you like to inject dependencies? [No]:
 ➤ Yes      

 Type the service name or use arrows up/down. Press enter to continue:
 ➤ logger.factory

 Type the service name or use arrows up/down. Press enter to continue:
 ➤ config.factory

 Type the service name or use arrows up/down. Press enter to continue:
 ➤ drush_generate_demo.helpers

 Would you like to create a route for this controller? [Yes]:
 ➤ 

 Route name [drush_generate_demo.example]:
 ➤ 

 Route path [/drush-generate-demo/example]:
 ➤ 

 Route title [Example]:
 ➤ 

 Route permission [access content]:
 ➤            

 The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/drush_generate_demo.routing.yml
 • /PROJECT-ROOT/modules/custom/drush_generate_demo/src/Controller/DrushGenerateDemoController.php

There you go again a new page controller available at /drush-generate-demo/example once you clear your cache and you can now edit the /src/Controller/DrushGenerateDemoController.php file to build your page with the custom drush_generate_demo.helpers service and logger.factory & config.factory services injected and available to use.

TIP: I personally find it hard to know exactly what services are available in Drupal so if you install the Devel module and then run ddev drush devel:services which will should you a list of all core & contrib services available on your project.


And there you go, hopefully I've been able to illustrate just how useful Drush generate can be and you now want to start using these commands your own development!