One of the greatest things of Drupal is Drush, the command line tool that was created to administer (and develop) Drupal. Out of the box Drush allows you to run a big number of commands to administer your site, from rebuilding caches to generating one time login link and a lot of other stuff.
Something great about Drush is that you can easily provide commands in your module and it even has a generator to scaffold the code you’ll need for your command. You can find more information on how to write a Drush command inside a module in the official documentation. In summary, for Drush >= 9, you need to do:
- Add a couple of lines to composer.json
- Add a drush.services.yml file to provide the services that will bring your commands to life
- Create the commands file
If you do that as expected, your command will be auto-discovered (if the module is enabled) and you’ll be able to use it once you rebuild caches.
However, the above method doesn’t work for disabled modules or for themes (no matter whether they’re enabled or not) because Drush only do auto-discover of commands inside enabled modules. So, if you need to add a command to a theme, you need to do things a little bit different. The following is a list of the key differences.
You can’t rely on Drupal to inject the dependencies you declare in the drush.services.yml file so, you can’t receive them in the constructor of your class. Instead of that, you need to rely on
\Drupal::service() function and be sure that you specify
@bootstrap full if you need to use dependencies from the services container.
You need to explicitly declare autoload configuration in the composer.json file so that Drush knows how to discover your classes. Add the following snippet to your composer.json (and update as needed):
Following the above example (and assuming your theme is named my_theme), you need to place your command file inside
Commands\my_theme folder (do not use src folder). Also, the namespace for your class should be
Drush\Commands\my_theme so that Drush can discover it.
Final difference is that you need to invoke your command using the path to the theme so that Drush knows where to find the command (remember that it’s not auto-discovered). So, following the above example, you need to run your command like this:
drush — include=docroot/themes/custom/my_theme mycommand
Creating commands inside Drupal themes is not so frequent in comparison to create them inside Drupal modules, but sometimes you may need to do it (e.g. to publish a contrib theme) so it’s useful to know the key differences to do it properly so that Drush can invoke your command.
I hope this has been useful for you :)