1

Is there any way to use dependency injection in a conditional way, i.e. only if a service exists similar to \Drupal::hasService().

I have a created a service in module A and in module B I have an EventSubscriber that should use the service from module A, but only if present of course.

Static I would do sth. like: if (\Drupal::hasService('module_a.my_service')) { \Drupal::service('module_a.my_service')->mymethod(); }

Is there any possibility to do this when injecting the service?

  • If it depends on it, when would it not be available? – Kevin Nov 28 '18 at 16:58
  • When the module A is not installed. It's optional. I have a couple of helper services in module A that are all optional, e.g. debugging, logging and notification functionalities. – Tobias Nov 28 '18 at 17:04
  • Just add some logic to your static create method which checks $container->has(‘service’), and pass null to the constructor for those that are missing. Then check the service is an instance of the class you expect it to be before you use it – Clive Nov 28 '18 at 17:06
  • But I don’t recommend that approach because it anchors to the wrong thing. Dependency injection doesn’t really work as a concept if the dependencies are optional. There are probably better practice ways to structure your code to base the decision on whether the module is installed or not, which is the real trigger, and not on whether a service exists – Clive Nov 28 '18 at 17:09
  • I see, you might be right, I'll check if I can restructure the code. Maybe additional submodules which implement the service calls and do not perform any check are better. – Tobias Nov 28 '18 at 17:20
1

One possible way to handle this situation is for your Module B to define a default, stub service with the same type signature (ie, Interface) as the one you need). Use that in the YAML. Then, in your Module A, you can alter the service to the one that the module provides.

That said, I do agree with the comments that you may be bypassing one of the benefits of DI, and creating a tight coupling between your two modules. Read the linked article to see when it is appropriate. Core uses it for the language and workspaces subsystems.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.