Dependency Injection
When to Use
Use dependency injection when forms need services (config factory, entity type manager, database, custom services).
Decision
| Situation | Choose | Why |
|---|---|---|
| Config factory only | FormBase::config() or $this->configFactory() | Already injected in FormBase |
| Multiple services | create() + __construct() | Proper DI pattern, testable |
| Entity queries | EntityTypeManagerInterface | Don't use \Drupal::entityTypeManager() |
| Database queries | Connection (database service) | Don't use \Drupal\Core\Database\Database::getConnection() |
| Custom module services | Inject via create() | Decoupled, mockable for tests |
Pattern
namespace Drupal\mymodule\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class SettingsForm extends ConfigFormBase {
protected $entityTypeManager;
public function __construct(
ConfigFactoryInterface $config_factory,
EntityTypeManagerInterface $entity_type_manager
) {
parent::__construct($config_factory);
$this->entityTypeManager = $entity_type_manager;
}
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('entity_type.manager')
);
}
protected function getEditableConfigNames() {
return ['mymodule.settings'];
}
public function getFormId() {
return 'mymodule_settings_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {
// Use injected service, not static call
$content_types = $this->entityTypeManager
->getStorage('node_type')
->loadMultiple();
// Build form...
return parent::buildForm($form, $form_state);
}
}
Common Services to Inject:
- config.factory - ConfigFactoryInterface
- entity_type.manager - EntityTypeManagerInterface
- database - Connection
- current_user - AccountProxyInterface
- messenger - MessengerInterface (though $this->messenger() works in FormBase)
- date.formatter - DateFormatterInterface
Common Mistakes
- Wrong: Using \Drupal::service() in form methods → Right: Not testable, tight coupling
- Wrong: Not calling parent::__construct() → Right: Config factory not initialized
- Wrong: Injecting too many services → Right: Form does too much, refactor to service
- Wrong: Forgetting to pass parent constructor args → Right: Fatal error
- Wrong: Using Database::getConnection() static call → Right: Should inject database service
See Also
- ConfigFormBase Pattern
- FormBase Pattern
- Reference: Dependency Injection in a Form
- Reference: core/modules/system/src/Form/SiteInformationForm.php