I am working with Symfony 6. The configuration of a route allows to add extra parameters which are passed to the controller:
index:
path: /somepage
controller: App\Controller\PageController::index
defaults:
title: 'Hello world!'
Is it possible to use a service as parameter? Something like:
defaults:
foo: '%some.container.parameter%' << Works, use container parameter?
logger: '#logger' << FAILS, use services as parameter?
This example does not work. While container parameters are correctly resolved, the services parameter is interpreted as string #logger instead of being resolved to the logger service.
Of course one could inject the complete service container into the PageController and use $this->container->get($logger); to get the services by its id. However, I found several sources, that injecting the services container is a bad idea which should be avoided.
So, is it possible to use a services as routing parameter?
Background
I would like to use a service parameter to make the controller more flexible when being used at different places.
For example the RedirectController can be used to create simple redirects without having to create a different controller for each redirected route.
Assume that the redirection of some routes is critical for some reason and needs more verbose logging and for example an alert notification via email.
Instead of creating different controllers and injecting different loggers, one could solve this by using different loggers as parameter:
legacy_one:
path: /somepage
controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController
defaults:
logger: '#defaultLogger'
legacy_two:
path: /otherpage
controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController
defaults:
logger: '#alertLogger'
Related
I have to work on a Symfony project that I never met before. There is a route that I'd like to figure out what script generates the result. Normally int the routing.yml the the _controller in the defaults tells this, but this route does not have any controller associated with:
vendorname_admin_generate_external_site_admin:
path: /admin/
host: "{current}.%vendorname_academic_base_host%"
defaults: {current: %vendorname_academic_base_subdomain%}
The two parameters are:
vendorname_academic_base_host: vendordomain.com
vendorname_academic_base_subdomain: developmentserver-vpn
Could you help me to understand what does this route definition do?
Because of the fact it is defining a specific host (ie, a domain name) as part of the route, makes me think that it's just an alias to an external website, that isn't actually in the same codebase. -- Also the fact its called 'external_site_admin'.
I've just added a similar route with a specific host, mine is still in the same codebase, but under a specific, shorter URL, but I defined my route as a template that I can use to setup as an alias.
I am building a restful services for my data using ASP.NET web api 2.
In the data model, I have an entity called "ServiceProvider" which provide "Service"(s).
so, I am building restful for those two entities.
the requirements is to build two restful services, one as follow
api/serviceProvider/{id}/services
which gives list of services provided by that provider.
as well, the requirements is to give the same data (services by provider) through this rest service
api/services?serviceProviderId={providerId}
so, I created two controllers, for "serviceProvider", and for "Service"
I already implemented the second call, by creating an action method in the "Service" controller with this signature
public IEnumerable<Service> GetServiceByProvider(int providerId)
because both are going to run the same code, can I just re-route the first call to the second one?
At the same time, not effecting the other actions in both controllers??
I tried to do this is the webApiConfig with no success
config.Routes.MapHttpRoute(name: "serviceByProvider",
routeTemplate: "api/serviceProvider/{id}/services",
defaults: new { controller = "Service", action = "GetServicesByProvider" });
where the "GetServiceByProvider" is the method name in the "Service" controller that will serve the second call
but without success
As I said there are other actions in both controllers I don't want to affect them by this routing.
Like I have the following
api/serviceProvider
api/serviceProvider/{id}
api/services/
api/services/{id}
.....
I decided to try again and duplicate your environment and found a problem in your route template. The parameter your route is expecting is called id but your GetServicesByProvider method accepts a parameter called providerId. The framework is looking for parameters with the same name. Changing this should get your routing working the way you want it to AND maintain all of your previous routes.
config.Routes.MapHttpRoute(
name: "serviceByProvider",
routeTemplate: "api/serviceProvider/{providerId}/services",
defaults: new { controller = "Service", action = "GetServicesByProvider" }
);
When i call my bundle as a service, everything working fine.
When i give a route to my bundle's controller, __contstruct stops working and the variables coming from config.yml file reasoning this.
These are warnings, but i need to get work to set my variables.
Warning: Missing argument 1 for
ATL15\GoogleAnalyticsBundle\Controller\GoogleAnalyticsController::__construct(),
called in
/var/www/vsy-bio/app/cache/dev/jms_diextra/controller_injectors/ATL15GoogleAnalyticsBundleControllerGoogleAnalyticsController.php
on line 13 and defined in
/var/www/vsy-bio/src/ATL15/GoogleAnalyticsBundle/Controller/GoogleAnalyticsController.php
on line 22
You need to call your controller as a service aswell in your routing like this:
hello:
pattern: /hello
defaults: { _controller: acme.hello.controller:indexAction }
See the documentation chapter How to define Controllers as Services.
I'm trying to learn learn how routing works in Symfony2, and so far everything I've read has examples like this:
blog:
path: /blog/{page}
defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 }
This routes requests to /blog/123 to the AcmeBlogBundle Blog controller's "index" action, and passes the 123 parameter as the "page" parameter to that controller action. If no page parameter is passed, then the page defaults to 1.
That's all well and good, but what if you want to simply have a convention based routing system that passes things through like this:
/{bundle}/{controller}/{action}
So, for a URL like this:
/acme/blog/index
It would then call AcmeBlogBundle Blog controller's "index" action.
No specific routing configuration is necessary, it simply infers the bundle, controller, and action from the URL. So you can continue adding bundles, controllers, and actions, and you don't need to modify the routing configuration. It just works.
If this isn't possible, can you at least infer the controller and action from the URL? E.g., perhaps you need a route that specifically identifies the bundle, but can we get the controller and action from the URL?
I read through the Symfony "The Book" page about routing, and I couldn't figure out a way to do this.
No way. This was considered as bad practice and so it was removed from symfony.
But you should take a look at the #Route annotation, as it simplifies configuring routes in such a nice way. Directly attached to the action, there is no lack between config and code.
I actually use automatic route generation for my api Rest, using the FOSRESTBundle, also I use NelmioApiDocBundle to generate the api doc.
To generate routes for the api this I have in my routing.yml
users:
type: rest
resource: Project\RESTBundle\Controller\UsersController
But for some actions I want to set my custom routing... If I try to add another route rule for an action it simply ignore it and generate the automatic route.
You have to declare the route with the same name right after the configuration you set. For example, the following works.
users:
type: rest
resource: Project\RESTBundle\Controller\UsersController
get_users:
pattern: /api/users/customUri.{_format}
defaults: { _controller: ProjectRESTBundle:Users:indexAction, _format: json }