Porting Commands to Drush 9
Drush 9 features a deep rewrite of our app, both user facing and internals. We created and open sourced AnnotatedCommand (example), OutputFormatters, and Config. We leveraged Symfony Console for our CLI fundamentals. For details on Drush9, see the video or slides from our Drupalcon Vienna presentation.
Unfortunately, old commandfiles such as example.drush.inc no longer load in Drush 9 (since beta5). We’ve made it relatively painless to port this code to Drush 9. The video below shows the drush generate command porting the migrate commands. Detailed instructions are below the video.
- Using Drush 9 on a working site, run
drush generate drush-command-file
.generate
is a wrapper for the Drupal Code Generator library. - You will be prompted for 2 pieces of information:
- Module name: example
- Absolute path to legacy Drush command file:
/path/to/example.drush.inc
- Drush writes 2 files to the Example module:
- drush.services.yml. No edits are needed unless you want to inject Drupal dependencies into your class (e.g. yml, class.
- ExampleCommands.php: Each item in
example_drush_command()
in your old commandfile has been transformed into an Annotated method in a new ExampleCommands file. Copy the body of your command callback functions into the corresponding method in ExampleCommands. Then modernize the code as below. Compare the Drush9 commands versus the Drush8 commands for guidance.- Replace
drush_log()
with$this->logger()->info()
or$this->logger()->warning()
or similar. - Replace
drush_get_option('foo')
with$options['foo'']
- Replace
drush_set_error()
withthrow new \Exception()
- Replace
drush_print()
with$this->output()->writeln()
- Replace
drush_sitealias_get_record()
as with$this->siteAliasManager()->getSelf()
. From there you can call getRoot(), getUri(), legacyRecord(), and other handy methods. In order for this to work, edit your class to implement SiteAliasManagerAwareInterface (LoginCommands is an example). - Optional - move user interaction to a @hook interact. Also, note the new
$this-io()->confirm()
and$this->io()->ask()
methods.
- Replace
- Run
drush cr
to add your commandfile to the Drupal container. - Congrats - your commands are now runnable in Drush9!
- Please post a patch if Example is a Contrib module.
- Please leave example.drush.inc in your module so that Drush 8 users may still use it.
I’m in #drush on IRC and Slack in case anyone wants help with porting.
Note that drush generate
knows how to generate controllers, plugins, config, services, libraries, etc. A blog post about generate is coming soon.
Moshe is available for hire as a consultant. Moshe has worked on Drupal core since 2001, and loves mentoring Drupal teams. Moshe loves to set up CI and developer workflows for PHP/JS teams.