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+.
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). Some autowire examples:
protected readonly Consolidation\OutputFormatters\FormatterManager $formatterManager
protected readonly Psr\Log\LoggerInterface $logger
protected readonly Drush\SiteAlias\ProcessManager $processManager
protected readonly Consolidation\SiteAlias\SiteAliasManagerInterface $siteAliasManager
protected readonly \Drush\Config\DrushConfig $drushConfig
protected readonly Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
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 WootStaticFactoryCommand extends Command
{
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'));
}
Inflection (deprecated)¶
Command classes used to implement the following interfaces. The replacement approach is listed below.
- CustomEventAwareInterface: Commands should fire their own events. Example: CacheCommands
- StdinAwareInterface: Read from stdin using the approach from ConfigSetCommand. This makes it possible to its test set stdin and then assert proper behavior.