Dependency Injection¶
Drush command files obtain references to the resources they need through a technique called dependency injection. When using this programing paradigm, a class by convention will never use the new
operator to instantiate dependencies. Instead, it will store the other objects it needs in class variables, and provide a way for other code to assign an object to that variable.
Tip
Drush 11 and prior required dependency injection via a drush.services.yml file. This approach is deprecated in Drush 12+ and removed in Drush 13.
Autowire¶
12.5+
Command files may inject Drush and Drupal services by adding the AutowireTrait to the class (example: PmCommands). This enables your Constructor parameter type hints to determine the injected service. When a type hint is insufficient, an #[Autowire] Attribute on the constructor property (with service: named argument) directs AutoWireTrait to the right service (example: FieldDefinitionCommands).
If your command is not found by Drush, add the -vvv
option for debug info about any service instantiation errors. If Autowire is still insufficient, a commandfile may implement its own create()
method (see below).
create() method¶
11.6+
Command files not using Autowire may inject services by adding a create() method to the commandfile. The passed in Container is a League container with a delegate to the Drupal container. Note that the type hint should be to Psr\Container\ContainerInterface
not Symfony\Component\DependencyInjection\ContainerInterface
. A create() method and constructor will look something like this:
class WootStaticFactoryCommands extends DrushCommands
{
protected $configFactory;
protected function __construct($configFactory)
{
$this->configFactory = $configFactory;
}
public static function create(Psr\Container\ContainerInterface $container): self
{
return new static($container->get('config.factory'));
}
createEarly() method¶
12.0+
Drush 12 supported a createEarly()
method. This is deprecated and instead put a #[CLI\Bootstrap(DrupalBootLevels::NONE)]
Attribute on the command class and inject dependencies via the usual __construct()
and AutowireTrait.
Note also that Drush commands packaged with Drupal modules are not discovered
until after Drupal bootstraps, and therefore cannot use createEarly()
. This
mechanism is only usable by PSR-4 discovered commands packaged with Composer
projects that are not Drupal modules.
Inflection¶
A command class may implement the following interfaces. When doing so, implement the corresponding trait to satisfy the interface.
- CustomEventAwareInterface: Allows command files to define and fire custom events that other command files can hook. Example: CacheCommands
- StdinAwareInterface: Read from standard input. This class contains facilities to redirect stdin to instead read from a file, e.g. in response to an option or argument value. Example: CacheCommands