November 11, 2021
Written by: Jon Kamke
Stop making everything a service just to use DI and start implementing ContainerInjectionInterface
Using dependency injection with services is fairly straightforward and common place, but dependency injection (DI) with a custom class that’s not a service is not seen very often in Drupal core. Stop making everything a service just to use DI and start implementing ContainerInjectionInterface and instantiate with \Drupal::classResolver();.
Below is an example custom class that implements ContainerInjectionInterface to inject the my_module.service service:
<?php
namespace Drupal\my_module\Entity;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\kraken_traceability\Service\MapService;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Define the data structure for a location.
*/
class LocationEntity implements ContainerInjectionInterface {
/**
* MapIngredientsService.
*
* @var \Drupal\my_module\Service\MapIngredientsService
*/
private $mapService;
/**
* Constructs a new LocationEntity.
*
* @param \Drupal\my_module\Service\MapService $mapService
* MapIngredientsService.
*/
public function __construct(MapService $mapService) {
$this->mapService = $mapService;
}
/**
* @inheritdoc
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('my_module.service'),
);
}
}
In a *.module file, for example, we can not instantiate this class with the new keyword like new LocationEntity() but instead use \Drupal::classResolver(); (see Drupal API for more info).
$locationEntity = \Drupal::classResolver(LocationEntity::class);