0
votes

I've got the following route definition

my_route:
    path:               /actual-path/
    defaults:
        _controller:    MyBundle:MyController:detail
        id:             application_id
    requirements:
        methods:        GET
        id:             \d+

The controller requires a parameter called $id.

But I don't want to use the $id in the url, I want to use a value that is available in $request->attributes->get('application_id')

There is a listener that will inject two parameters (application_id and application) into the request object as attributes prior to the routing process, so this value is in there. (It would be easy to also inject it into the RequestContext).

Is there a way I can use attributes values from the Request or RequestContext object in my routing as defaults?


Now I could simply do $request->attributes->get('application_id') in my controller. But this controller will be used in several cases. In other cases the $id is to be passed through the url. I find it cleaner to set the id in the routing than build a if-else clause in the controller somewhere.

1
Controller::myAction(Request $request, $application_id) will do what you want. The controller resolver will use the argument names to automatically pull data out of the request object. Your question is a bit confusing. If the id is not present in the url then just have your listener add in the application_id. In any event, I suspect your route definition will need a bit more work.Cerad
Thing is, I can't change the controller:action, as that is a generic action (located in the vendor dir). So the controller is expecting id, but the value in Request is application_id. So basically, I would need some kind of mapping in the routing configuration.DoppyNL
I suppose you might be able to do it with expressions: symfony.com/doc/current/book/…. Otherwise, add another kernel listener to do it.Cerad
I was looking into that already, but I'm afraid that would also become a bit of a mess. I guess my best chance is to handle it is to extend the controller and handle it there. If the id === null for instance, use the application_id for instance.DoppyNL
Listeners are easy especially if you have more than one route with this sort of thing.Cerad

1 Answers

0
votes

It appears not to be possible to do "mapping" between variables in the request object and the parameters you need to be required in your route/controller-action. I think this would be a good thing, as it would become quite complex otherwise.

I went with the solution to extend the controller and build in a small switch there.

Basically, if the route specifies id === null, it will do a fallback to application_id that is in the Request object. Otherwise it will use the value provided. I just need to set a requirement on id on the routes that must not use the fallback.

All without running an additional Listener which might be a bit "expensive" in processing time (for each request).

Example of routes:

my_route:
    path:               /actual-path/
    defaults:
        _controller:    MyBundle:MyController:detail
        id:             null
    requirements:
        methods:        GET

my_other_route:
    path:               /other-path/{id}
    defaults:
        _controller:    MyBundle:MyController:detail
    requirements:
        methods:        GET
        id:             \d+

And how to handle this in your controller:

    // fallback to system id
    if ($id === null) {
        $id = $request->attributes->get('administration_id', null);
    }

Because you extend the controller/action, you could also change the name of the parameter in the action (as long as the type does not change).

I did not do this, as I could quite easily put the switch between the provided id and the fallback from the listener in another method.