4

when trying to use a service in drupal actually there is 3 ways , what is the preferred way to use a service and why :

  1. passing dependencies directly through the constructor:

    public function __construct(AccountProxyInterface $current_user) {
    
    }
    
  2. passing the dependencies through the create() method wich look to me the same as injecting it through the __construct(), with the only difference , an instance will be created eah time (no singleton design pattern - not same instance will be reused)

      public static function create(ContainerInterface $container)
  {
    //1.getting service from the service container.
    $Door = $container->get('custom_service.door');
    //2.create a new object of current class, and Inject the dependency  object into the constructor
    return new static($Door);
  }

  //constructor receive the dependency set by the create() method
  public function __construct(Door $Door)
  {
    kint($Door);
  }
  1. just get get the service from the service container and no need to inject it using :
    $Door = \Drupal::service('custom_service.door')
  • 4
    You should always inject your arguments and typehint them to their interface counterpart whenever possible. Assigning instance variables from the global container is not advised. \Drupal::service... is largely used from procedural code when not in an OOP context. – Kevin Jan 15 at 21:47
  • 5
    2. also has a specific context in Drupal, it is a factory method pattern used to instantiate controllers and plugins. So there is no preferred way, each one is used in a different context. – 4k4 Jan 15 at 22:09
  • @4k4 can you explain the diffent contexts, so that I know when to use create factory method and when to inject directly into the constructor. – Marwen Amri Jan 15 at 23:28
5
  1. The standard way to inject services in other services is passing dependencies directly through the constructor:

    mymodule.services.yml:

    services:
      mymodule.foo_service:
        class: Drupal\mymodule\FooService
        arguments: ['@current_user']
    
  2. While you can define a factory method in *.services.yml, see https://symfony.com/doc/current/service_container/factories.html, in Drupal the most common places for this are Controllers and Plugins which implement ContainerInjectionInterface::create or ContainerFactoryPluginInterface::create. See How do I use dependency injection on \Drupal::moduleHandler() to a Controller?

  3. \Drupal::service... is largely used from procedural code when not in an OOP context, like hooks or static callbacks. See the comment from @Kevin.

  • 1
    Also worth metion that you can inject dependencies (services or parameters) to a class that is not a service and will be used on procedural code like hooks by making your class implement \Drupal\Core\DependencyInjection\ContainerInjectionInterface and by calling it in your hook using $instance = \Drupal::classResolver('\Drupal\my_module\MyAwesomeClass');. Is not a service but will use services though. – d70rr3s Jan 16 at 9:07
  • Is the linked question 226997 still a recommended pattern? According to this blog post the constructor should be considered internal and subject to changes. – Hudri Jan 16 at 9:47
  • @Hudri, this is a good point, although it's not that you shouldn't use the design pattern anymore, it's about how you can extend existing controllers which are built with this design pattern. – 4k4 Jan 16 at 10:14
  • For my own understanding: If I'm writing my own standalone class -> __construct(Services...) OK. As soon as I'm extending from another class like e.g. ControllerBase or PluginBase -> better leave the constructor alone and $container->get() the service inside create()? – Hudri Jan 16 at 10:35
  • No, the linked blog post is not about writing a new controller or plugin by extending a base class in your own module, it's about extending existing core/contrib controllers and plugins. – 4k4 Jan 16 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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