... because extending classes should not be allowed to use it, but implement ContainerInjectionInterface for their dependencies.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

amateescu’s picture

Status: Active » Needs review
FileSize
1.07 KB

Like this. Let's see who's doing it wrong.

We'll also need a good comment there to explain why.

msonnabaum’s picture

Yes, please.

This has already caused confusion, and there's a language feature that makes it perfectly clear. Let's use it.

tstoeckler’s picture

Attempt at a comment:

This method is marked private to prevent sub-classes from retrieving services from the container through it. Instead \Drupal\Core\DependencyInjection\ContainerInjectionInterface should be used for injecting services.

Status: Needs review » Needs work

The last submitted patch, 2110643.patch, failed testing.

amateescu’s picture

Status: Needs work » Needs review
FileSize
4.07 KB
4.3 KB

Surprisingly few offenders, I guess we must be doing something right.

Crell’s picture

Mark asked me to weigh in here. My stance on privates is currently: #2081945-11: [Policy, no patch] Reintroduce 'private' visibility to object-oriented code..

If we do reintroduce privates, then #5 seems a logical place to do it. Although I will note that Symfony's Controller base class has a protected container() method. :-) I think our explanation for doing it differently is that we're trying to educate people about injection, and controllers/forms are the biggest touch-point so it makes more people learn what good injection is.

msonnabaum’s picture

It's not just that, it's that we want to provide a base class that offers some common services, without making every controller/form container-aware.

This issue came up after a discussion on IRC where there was confusion around whether to inject additional dependencies or to just use the container method that's there. This tells me that we need to clear things up by just making container private.

tim.plunkett’s picture

+++ b/core/modules/locale/lib/Drupal/locale/Controller/LocaleController.php
@@ -51,8 +51,8 @@ public function checkTranslation() {
-      'filter' => drupal_get_form(TranslateFilterForm::create($this->container())),
-      'form' => drupal_get_form(TranslateEditForm::create($this->container())),
+      'filter' => drupal_get_form(TranslateFilterForm::create(\Drupal::getContainer())),
+      'form' => drupal_get_form(TranslateEditForm::create(\Drupal::getContainer())),

See #2112711: Provide an easier mechanism for using drupal_get_form() directly for a way to clean this up.

tim.plunkett’s picture

This is a major issue. Providing the container does not help anyone learn injection, and was not the intention of these classes.

This is best paired with #2110501: ControllerBase should implement ContainerInjectionInterface like FormBase

xjm’s picture

Issue tags: +beta blocker

Discussed on the phone with @Dries, @webchick, @msonnabaum, @tim.plunkett, and @alexpott -- this should be considered a beta blocker given the DX impact.

dawehner’s picture

Let's keep the patch as simple as possible.

damiankloip’s picture

So child classes have to use injection but the base class doesn't, and just calls to \Drupal. This is getting nuts IMO.

damiankloip’s picture

So child classes have to use injection but the base class doesn't, and just calls to \Drupal. People will just never write tests for this stuff. This is getting nuts IMO.

dawehner’s picture

In general controllers should avoid containing logic from my beginning.

So child classes have to use injection but the base class doesn't, and just calls to \Drupal. People will just never write tests for this stuff. This is getting nuts IMO.

Well, this patch at least does not make the situation worse.
When I would have to write my code in contrib I would probably inject everything properly, though things like ->url()/t() aren't really worth to be unit tested. We should maybe provide helper methods on the base unit test, if possible.

dawehner’s picture

Discussed on the phone with @Dries, @webchick, @msonnabaum, @tim.plunkett, and @alexpott -- this should be considered a beta blocker given the DX impact.

Well, it certainly does not "improve" the DX, though forcing people to do things better is a good thing.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

I think this is fine as it is.

xjm’s picture

Issue tags: -beta blocker +beta target

Discussed with @catch; it'd technically be okay to put this in after the beta. (Doesn't affect that this issue is RTBC anyway; just major and beta blocker don't make sense together.) :)

catch’s picture

I agree with Damian here. Don't particularly object to this, but I think people will just call \Drupal if they're doing it wrong anyway, so leaving for someone else.

amateescu’s picture

The alternative would be to admit that all (most?) controllers should be ContainerAware after all? :)

The argumentation for that is that people who want to do things the Right Way will create a service for the main logic of their stuff and test it, so controllers will be tiny glue code, and people who don't care about that or they are just not experienced enough will write "bad" code disregarding all the hurdles we put in place.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

I think this makes sense. It makes it so that dependency injection happens consistently in all "user-space" code.

Committed and pushed to 8.x. Thanks!

This was already covered in the change notice at https://drupal.org/node/2168147.

mondrake’s picture

Looks like there is a leftover $this->container() call in ConfigFormBase?

I am getting a

PHP Fatal error: Call to private method Drupal\Core\Form\FormBase::container() from context 'Drupal\Core\Form\ConfigFormBase' in /[...]/core/lib/Drupal/Core/Form/ConfigFormBase.php on line 79

EDIT

Created #2168799: ConfigFormBase fails when invoking $this->container().

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.