2

In the presentation given in Portland by Kat Bailey in May, registering a controller class as a service was highly discouraged, however a lot has changed since then and I wanted to check if this is still the case.

It is well supported in the code and you can route to actions in the controller you registered via reference to the service id, such as.

 defaults:
   _content: 'my.controller:myAction'

Rather than referring to the controller class directly.

I can foresee at least a couple of use cases, primarily at the moment it allows an easy option to override / extend an entire controller via replacing the service.

The only other way I know to do that at the moment would be to register an event subscriber to override all the routes to a particular controller which would be rather long winded. Views currently overrides individual routes controller actions this way to reset routes for views with paths (which makes sense as that is more of a path by path based surgical strike).

I don't won't to start down a path that turns out to be a big D8 anti-pattern, but if service controllers are bad, what is the alternative to allow simple replacement of a controller in another module?

  • Without watching that video again I can't remember what the problem with controllers as services is (Symfony certainly don't agree that they're a bad thing), could you expand on Kat's reasons for the discouragement? – Clive Nov 15 '13 at 15:49
  • @Clive Actually, the reason that link is to the cookbook rather than a general documentation on controllers, is specifically because it is frowned upon, by some. Source – Letharion Nov 15 '13 at 16:07
  • Thanks @Letharion - if Potencier says it's bad, that's good enough for me ;) – Clive Nov 15 '13 at 16:09
  • 1
    @Clive That's been my thinking as well :) I posted some more details as an answer below. – Letharion Nov 15 '13 at 16:11
  • 1
    The main reason for discouragement seemed to be the proliferation of services that would ensue. I agree that Potencier adds weight to an arguement but the differences between Drupal lower level Symfony could push the other way. For example the Symfony cookbook states "This is especially useful when developing an open-source bundle or any bundle that will be used in many different projects." re controllers as services. Drupal Contrib..... – chris_hall_hu_cheng Nov 15 '13 at 16:49
5

From a Symfony docs discussion

fabpot commented

@lsmith77 is right. I strongly believe that this is NOT a best practice. I don't recommend it at all. That's why it's not in the book and explained in a cookbook entry.

mahono commented

It would be nice to understand why what is (not) best practice. @fabpot: could you give some more info why you think so (or is there more information about that somewhere else?) To me most important is to learn best practices how to make my bundles customizable.

fabpot commented

The DIC mostly helps manage "global" objects. Controllers are not global objects. Moreover, a controller should be as thin as possible. It's mainly the glue between your Model and the View/Templates. So, if you need to be able to customize then, it probably means that you need to refactor them and extract the business logic from them.

With that said, here's a blogpost arguing for controllers as services: http://pooteeweet.org/blog/1947

  • I can see this is going to be hard to decide :) whilst I agree that controllers should be slim many controllers in Core (admittedly still in a high state of flux) implement ContainerInjectionInterface so are either 'fat' because and need the injected container to allow for testing or they are 'thin' and should be refactored to extend ControllerBase instead. The arguement that controller should be simple to refactor is fine if it is your code but not if you don't want to hack core or contrib in your project. I am still on the fence somewhat. – chris_hall_hu_cheng Nov 15 '13 at 16:26
  • Maybe one big difference is whether you write a one-off application where inside the controller class you can make strong assumptions on how exactly the DIC is wired up, OR you write a CMS where the controller class is going to be part of the framework, and reused in many different scenarios, with different DIC configurations. – donquixote Nov 15 '13 at 18:31
2

This session by Tim Plunkett in Prague 2013 was insightful:
https://prague2013.drupal.org/session/drupal-8-routing-method-madness

In the questions part I asked about why controllers are not services. I think the reply was that we get too many services..

Too bad you can't hear the questions in the video.
I have a suggestion for "homework": You have a look at the video and figure out at which minute he talks about controllers vs services. Then you add the timing to this answer :) Must be somewhere in the questions part.

Otherwise, I think the place to ask is IRC #drupal-contribute. And then extend this answer, so others can benefit from it.

  • hm, can't find it myself now.. – donquixote Nov 15 '13 at 16:00
  • Cheers for the link I will listen to that on the bus home, I will pursue and update here when I get a definitive view on it ;) – chris_hall_hu_cheng Nov 15 '13 at 16:05
  • Answer to your question was at about 34 min mark, mainly against the proliferation of services but als primarily referencing core rather than contrib. – chris_hall_hu_cheng Nov 15 '13 at 20:56
2

I think the "best practice" for Drupal 8 will be:

1) Controllers are not services, but use either ControllerBase or the traits we're planning to build to get at "common" services. They may, optionally, use the ContainerInjectionInterface to get other services.

2) Controllers are thin enough that you wouldn't want to bother swapping them. If you really need to there's still a way to alter a route definition, akin to hook_menu_alter.

3) Any really significant logic belongs in a separate service from the controller, and that service should be unit tested. The Controller is really just glue code.

Controller services are supported and there are some cases where they're better, such as the HtmlPageController wrapper, but those are unusual. The typical case will be ControllerBase/ContainerInjectionInterface.

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.