Skip to content

Dependency Injection

When to Use

Media source plugin needs services like HTTP client, logger, cache, file system, or custom services.

Decision

Service Use When Container Service ID
http_client Fetching remote resources, API calls http_client
logger.factory Error logging, debugging logger.factory → get('yourmodule')
cache.default Caching API responses, metadata cache.default
file_system Thumbnail downloads, file operations file_system
token Directory paths with tokens token
Custom service Module-specific logic yourmodule.service_name

Pattern

Service injection in plugin (15 lines):

use Drupal\Core\Cache\CacheBackendInterface;
use GuzzleHttp\ClientInterface;
use Psr\Log\LoggerInterface;

class CustomApi extends MediaSourceBase {
  protected ClientInterface $httpClient;
  protected LoggerInterface $logger;
  protected CacheBackendInterface $cache;

  public function __construct(
    array $configuration, $plugin_id, $plugin_definition,
    EntityTypeManagerInterface $entity_type_manager,
    EntityFieldManagerInterface $entity_field_manager,
    FieldTypePluginManagerInterface $field_type_manager,
    ConfigFactoryInterface $config_factory,
    ClientInterface $http_client,
    LoggerInterface $logger,
    CacheBackendInterface $cache,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition,
      $entity_type_manager, $entity_field_manager, $field_type_manager, $config_factory);
    $this->httpClient = $http_client;
    $this->logger = $logger;
    $this->cache = $cache;
  }

  public static function create(ContainerInterface $container, array $configuration,
    $plugin_id, $plugin_definition): static {
    return new static(
      $configuration, $plugin_id, $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('entity_field.manager'),
      $container->get('plugin.manager.field.field_type'),
      $container->get('config.factory'),
      $container->get('http_client'),
      $container->get('logger.factory')->get('yourmodule'),
      $container->get('cache.default'),
    );
  }
}

Common Mistakes

  • Using \Drupal::service() in plugins → Breaks testability, violates DI principles
  • Not calling parent constructor → Missing base services, plugin breaks
  • Forgetting create() method → Services not injected, constructor fails
  • Wrong parent constructor signature → Parameter order mismatches cause errors
  • Injecting unnecessary services → Adds complexity, slows instantiation

WHY: - DI over static calls: \Drupal::service() creates global dependencies; DI enables unit testing with mocked services - Parent constructor: MediaSourceBase requires 4 core services; not calling parent means these aren't initialized - create() is factory: Plugins instantiated via static factory; forgetting this means services never injected

See Also

  • Previous: Thumbnail Generation
  • Next: Validation Constraints
  • Reference: https://www.drupal.org/docs/drupal-apis/services-and-dependency-injection/dependency-injection-in-plugin-block
  • Reference: https://drupalize.me/topic/dependency-injection