8000 [DX] Controller as a service, favoring tags over class level @Route() · Issue #12915 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
8000

[DX] Controller as a service, favoring tags over class level @Route() #12915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
linaori opened this issue Dec 9, 2014 · 8 comments
Closed

[DX] Controller as a service, favoring tags over class level @Route() #12915

linaori opened this issue Dec 9, 2014 · 8 comments

Comments

@linaori
Copy link
Contributor
linaori commented Dec 9, 2014

Currently when using Controller as a Service with the SensioFrameworkExtraBundle, you will have to add an @Route(service="acme_hello.controller.my_controller"). This feels unnatural, as it has nothing to do with routes.

As of 2.4, Command as a Service was introduced. That made configuring the command really easy, you only have to add a tag to your service: - { name: console.command }.

My suggestion is to drop support for the service option in the @Route (and make both possible in 2.7) in favor of a tag on the service. The configuration could look like:

services:
    acme_hello.controller.my_controller:
        class: Acme\HelloBundle\Controller\MyController
        tags:
            -  { name: framework.controller } # or perhaps: request.controller

This configuration feels far more natural and is in line with command configuration. I know this is supposed to be part if the SensioFrameworkExtraBundle, but getting feedback there is hard.

@yannickl88
Copy link

👍

@stof
Copy link
Member
stof commented Dec 9, 2014

@iltar the issue is that controllers and command resolving are totally different:

  • commands are registered in the application and they provide a name (and aliases) to be used to call them (this is also why commands are not lazy-loaded currently btw)

  • controllers are created by the ControllerResolver based on the _controller attribute of the Request, which is generally coming from your routing (it could come from another source though).

    When using controllers as a service, the _controller attribute has to look like acme_hello.controller.my_controller:sayHello instead of AcmeHelloBundle:My:sayHello for an instance creation.
    So knowing that the route needs to reference a service is related to the route.

How would your tag work to build the route properly ?

@linaori
Copy link
Contributor Author
linaori commented Dec 9, 2014

@stof I tried to do some research before I actually posted this suggestion, but my knowledge is still limited. From what I can see, the AnnotatedRouteControllerLoader does some guessing on whether it's supposed to be a service or not.

Instead of trying to find out runtime if this is supposed to be a service, this can already be collected when collecting the tags during container compilation. During this process, it can be mapped as following:

$controllers = [];
$tags = $container->findTaggedServiceIds('framework.controller');
foreach ($tags as $id => $tag) {
    $controllers[$container->getDefinition($id)->getClass()] = $id;
}

With this, you have a nice map: ['Foo\Bar\Controller\MainController' => 'foo_bar.controller.main']. The SensioFrameworkExtraBundle will have to do some resolving which won't be much different from what it is now.

So knowing that the route needs to reference a service is related to the route.

Imo this only from a framework perspective. As developer I find it strange to add this in @Route.

Having this information available because it's compiled gives other using app/console:

  • Which service controllers are defined?
  • Which service controller has which routes?

Tags would also allow other options to be passed along easily, without having to update an annotation, think about a priority to overwrite certain routes as simple example.

@stof
Copy link
Member
stof commented Dec 9, 2014

Which service controllers are defined?

But this would not allow answering this question either, given that only routes defined using annotations would require being tagged.

Which service controller has which routes?

I don't see how this would answer this question.

Tags would also allow other options to be passed along easily, without having to update an annotation, think about a priority to overwrite certain routes as simple example.

Please don't try putting routing definition in the DIC config. It will be mixing things.

@fabpot fabpot closed this as completed Feb 11, 2015
@Tobion
Copy link
Contributor
Tobion commented Feb 11, 2015

I think I have another idea to solve this problem that the route (annotation) doesn't want to know the service id. We could say when a full class name is given in as a controller like _controller: Acme\HelloBundle\Controller\MyController::myAction, the controller resolver would just ask the DI for a service definition with that class name and use it. It's rather unlikely that the same controller class is used in multiple service definitions.

This way you also don't need to annotate the service because the reflection would simply set the current controller class and action as _controller.

This sounds so simple and intuitive to me. Am I missing something?

@Tobion
Copy link
Contributor
Tobion commented Feb 11, 2015

@stof @fabpot any opinion?

@fabpot
Copy link
Member
fabpot commented Feb 11, 2015

... except that nothing is doing that right now; nowhere do we ask the DI for a service associated with a class name. The closer we had in the past is the interface support that was quickly dropped.

@stof
Copy link
Member
stof commented Aug 1, 2015

And btw for anyone looking at @Tobion's suggestion again, this would break the support for controllers not defined as services, because Acme\HelloBundle\Controller\MyController::myAction is a perfectly supported controller definition currently

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
0