Problem/Motivation

Drupal currently has two main ways of getting the service discovery container:

  1. \Drupal
  2. ContainerInjectionInterface or similar 'proper' injection pattern.

\Drupal is intended to be used by legacy procedural code which does not have an injection path.

Other service discovery should follow the inversion-of-control principle where services are injected into consumer classes without keeping a reference to the container itself. This principle is satisfied by the ContainerInjectionInterface pattern, and is also generally satisfied by the arguments property of the service definition file.

Proposed resolution

  • #2380293: Properly inject services into ModuleInstaller discovered that some re-thinking is required for the 'lazy' status of some services. \Drupal deferred instantiation of some services until needed, and removing it led to large memory usage. So: Discover which services need deferred instantiation as we go along.
  • Convert controllers/forms which use service traits, such as StringTranslationTrait. One issue per trait.
  • Make changes per \Drupal service method. There will be some patch conflicts based on which lands first. Since we're injecting the dependencies, we'll probably end up changing the constructor per patch and that will lead to rerolls. We should also look for the service name itself, so we can convert \Drupal::get() for the equivalent service.
  • We do this for non-test code under this issue.
  • Then we can concentrate on making the tests happen: #2066993: Use \Drupal consistently in tests For instance, the majority of occurrences of \Drupal::root() appear in tests.
  • #2066993: Use \Drupal consistently in tests suffers a bit from the same reviewability problem as this one, but could be rescoped to work per-method. There would be fewer patch conflicts, because the container is injected into the test class whole.
  • Then the plan all goes to heck when we get to \Drupal::get() and it's utter chaos. :-)

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Mile23 created an issue. See original summary.

Mile23’s picture

Mile23’s picture

xjm’s picture

https://www.drupal.org/core/scope has some guidelines on how to best scope issues (based on our attempts and mistakes in the past to make codebase-wide changes). Let's brainstorm a bit about how we can make these changes in the most successful way, so we don't lose time needing to redo things across many issues.

I think one patch per controller is going to be ultimately difficult to complete effectively. See https://www.drupal.org/core/scope#consistency for example. Instead, what about grouping issues by the specific type of fix? For example, we could take one method on \Drupal, replace all its uses in code that should have the dependency injected, and then deprecate the method.

It would also be good to document the overall plan and scope here before we start.

Thanks for your ongoing and seemingly tireless efforts to clean up these kinds of technical debt in Drupal 8. On the recent Drupal survey a "fully object-oriented API" was the top thing to improve for developers. I think cleanups like these are exactly what that means.

Mile23’s picture

Totally agreed that changes have to be consistent and reviewable.

Let's kick it this way:

  • As you say, we can change per \Drupal method, though there will be some patch conflicts based on which lands first. Since we're injecting the dependencies, we'll have to change the constructor per patch and that will lead to rerolls. We should also look for the service name itself, so we can convert \Drupal::get() for the equivalent service.
  • We do this for non-test code under this issue.
  • Then we can concentrate on making the tests happen: #2066993: Use \Drupal consistently in tests For instance, the majority of occurrences of \Drupal::root() appear in tests.
  • #2066993: Use \Drupal consistently in tests suffers a bit from the same reviewability problem as this one, but could be rescoped to work per-method. There would be fewer patch conflicts, because the container is injected into the test class whole.
  • Then the plan all goes to heck when we get to \Drupal::get() and it's utter chaos. :-)

There's also a question of metrics, because #2380293: Properly inject services into ModuleInstaller was added and then removed due to memory usage. Do we have a standard way to evaluate this?

Mile23’s picture

Issue summary: View changes

Updated issue summary.

Mile23’s picture

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Mile23’s picture

xjm’s picture

This is listed as the next step for #2704871: Replace usages of deprecated method drupal_render() but I don't actually see an explicit followup for the render usage yet; can we add one? Thanks!

Mile23’s picture

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Mile23’s picture

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Hardik_Patel_12’s picture

Hardik_Patel_12’s picture

Hardik_Patel_12’s picture

xjm’s picture

As a reminder, we should not "Replace calls to \Drupal in foo.module". Instead, we should "Replace calls to \Drupal::bar() in baz usecase." Reference: https://www.drupal.org/core/scope#files

For example, #2776385: Replace non-test usages of \Drupal::transliteration() with IoC injection has correct issue scope, but #3110333: Reduce \Drupal usage in user module run-time code does not.

Thanks for your efforts to help work on these issues!

xjm’s picture

Alright, I've closed several issues that were incorrectly scoped as duplicates of the meta:

It's better have issues that look one by one at \Drupal::foo() usage on a per-method basis, rather than a per-module basis, and fix them core-wide as appropriate. And if the scope of that turns out to be too large, then we should break it down an additional level with (e.g.) "Use $this->foo() instead of \Drupal::foo() in form classes."

I definitely recommend novice contributors and their mentors carefully read https://www.drupal.org/core/scope and then use that as a guide for creating and organizing cleanups such as these. That way, you will have more success at getting these cleanups done, and it will be easier for reviewers and committers too.

Note that there is also #3113904: [META] Replace t() calls inside of classes to use injected $this->t() where available, so be sure not to duplicate that issue either. (Some of those may also have problematic scope by module, but at least it's only one type of change, and there are enough uses of t() that breaking it down some is necessary.)

Thanks everyone!

jungle’s picture

  • Just created a bunch of child issues according to #23
  • It's time to talking about Trait again. the comment of #2134513 was 4 years ago. I think traits can be used to clean up \Drupal::foo() usages in tests at least. In general, no IOC injection in tests .

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.