Score:4

Can services be autowired?

br flag

In drupal 8, each time we used to declare a class as a service by adding it to [module name].services.yml and then injecting it in the constructor of a different class. However, according to this answer https://stackoverflow.com/questions/44809739/is-there-a-way-to-inject-entitymanager-into-a-service , in newer symfony versions, we can inject a service without defining the class in services.yml. does it apply to drupal 9 and 10 since they use newer versions of symfony?

Mario Steinitz avatar
id flag
https://www.drupal.org/node/3218156
Mario Steinitz avatar
id flag
PS.: Sorry, not a fully fledged answer. I'm mobile and still trying the newly installed Stack Exchange app. But above link should point you to what's currently possible and what not.
br flag
Thanks @MarioSteinitz , apparently no need to define the service anymore
Score:6
id flag

Having a bit more time today, so I'll elaborate on my comment to your question:

Autowiring would've been possible with the Symfony version used by Drupal 8 already. However, Drupal is using a plethora of services and autowiring wasn't highest priority when moving the architecture from Drupal 7 to 8.

Therefore, support for Symfony autowiring wasn't added to Drupal before version 9.3. See this change record for more details:

https://www.drupal.org/node/3218156

Still, Drupal Core services couldn't be autowired by that time, due to services in Drupal are using string identifiers in their service declarations rather than fully qualified class/interface names.

Implementing a class referencing interfaces or classes of such services as method parameter type wouldn't allow Symfony to identify the intended Core service to inject when autowring.

So you still had to define the Core service parameters, but could use autowiring for your own services, if you defined them with class or interface alias.

This has been changed as of Drupal 10.1, where the interfaces and class namespaces have been added to the core services definitions. See this change record as reference:

https://www.drupal.org/project/drupal/issues/3049525

For 3rd party module services and even some modules provided by Drupal Core, this may or may not have been done yet. Before using them in an autowiring scenario, you'll have to check those manually.

To sum it up: Symfony autowiring is possible in Drupal since version 9.3 when using services as arguments that already define their PHP class or interface aliases in their service definitions. Core service parameters had to be defined manually, because they didn't define their aliases. As of version 10.1 you can autowire including Core service parameters, but still should check for 3rd party module services.

Side note:

I have to admit, that I never was nor am a huge fan of autowiring and still prefer defining the arguments of all my classes and services manually.

It may be a little bit more work, but it allows me to find dependencies at a glance just by opening my modules' *.services.yml file (or in very rare cases the modules' service provider class).

br flag
What a great answer ! Thank Youu !
br flag
I totally agree, i am bkt a fan of autowirinf too. But do you usually call your services after defining them in sevices.yml using Drupal::service(..service..)or do you inject them in the constructor as arguments?
Mario Steinitz avatar
id flag
Definitely constructor arguments, if that's an option. Only in very rare cases using the container. (Somethimes having them as class properties isn't feasible.) Then usually within a protected getter method of my classes.
Mario Steinitz avatar
id flag
PS.: I *might* have to add, that autowired class attributes are possible in Symfony 6. So with Drupal 10 one *could* use service names to initialize class properties in the constructors without the services defining their class aliases. ( https://symfony.com/blog/new-in-symfony-6-1-service-autowiring-attributes ) - But I don't want to suggest to anyone reading here to deviate too far from Drupal best practices. And AFAIK they still are injecting required services in the constructor. No autowiring. ;)
br flag
Wow! Thank you so much !!
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.