Symfony2 i18n routing - defining an array of requirements - symfony

Is it possible to define an array of locales used in Symfony2 routing rules, so that I won't have to repeat it over and over in every route and alter it for each route separately in case I change the supported languages list?
I know it's very easy to do a quick search & replace in routing.yml, but the issue's scope could be easily expanded so that it provokes a question like this: is it possible to provide this locale array externally (i.e. to have it read from a database)?
For clarification - here is an example of what I have now:
page_show:
pattern: /{_locale}/page/{slug}
defaults: { _controller: myCompanymyBundle:Cms:pageShow }
requirements:
_locale: en|pl
slug: "[^,]+"
news_archive:
pattern: /{_locale}/news/archive
defaults: { _controller: myCompanymyBundle:Cms:newsArchive }
requirements:
_locale: en|pl
And here is an example of what I'd like to have:
page_show:
pattern: /{_locale}/page/{slug}
defaults: { _controller: myCompanymyBundle:Cms:pageShow }
requirements:
_locale: languages
slug: "[^,]+"
news_archive:
pattern: /{_locale}/news/archive
defaults: { _controller: myCompanymyBundle:Cms:newsArchive }
requirements:
_locale: languages
Where languages is an array, be it a YAML array or a PHP array provided externally; it's not really substantial.
This could be very helpful to further ease the configuration of the application I'm writing. I'd like to extract as much configuration as possible into the config.yml file. So that if I decide that, for instance, I want to add a new language quickly and I already support it in the business logic and templating layers, I just have to modify the languages array in config.yml and voila, it's done.

Thats something that bugs me every time. The only thing I could offer is to put your requirement params into app/config/parameters.yml
# src/App/Resources/config/routing.yml
sport:
pattern: /{_locale}/{sport}
defaults: { _controller: App:Vote:vote }
requirements: { _locale: %routing_locales%, sport: %routing_sports% }
# app/config/parameters.yml
parameters:
# routing requirement regex
routing_sports: 'hockey|football' # available sports so far
routing_locales: 'de|fr' # available locales so far

Related

In Symfony is it possible to if a route matched, forward to other route

I have two routes in two separated bundles: bundleA_route, bundleB_route. In my /app/config/routing.yml I load them as resources like:
bundle_a_routing:
resource: "#SomeABundle/Resources/config/routing.yml"
prefix: /
bundle_b_routing:
resource: "#SomeBBundle/Resources/config/routing.yml"
prefix: /
In most cases this sequence is required, first of all try to match on routes in bundle_a_routing, and then try to match on routes in bundle_b_routing, but in only one case I want to make an exception, I want a single route defined in bundle_b_routing to be matched before the more "concessive" route defined in bundle_a_routing:
route_in_bundle_a:
path: /admin/{path}
defaults: { _controller: SomeABundle:SomeCtrl:someAction }
methods: [GET]
requirements:
path: ^(.*)$
route_in_bundle_b:
path: /admin/download/{formId}/{fileName}
defaults: { _controller: SomeBBundle:SomeOtherCtrl:someOtherAction }
methods: [GET]
requirements:
formId: \d+
fileName: ^([a-fA-F0-9]{32}(?:\.[a-zA-Z0-9]{1,222})?)$
Now the request URI "http://servername/web/app_dev.php/admin/download/12/23d2fff7f606e93acac9ede5b4e2b394.png" matches the first, but I want to match the second...what is the official scenario in cases like this?
You should change the order in which you are importing routes, so the route http://servername/web/app_dev.php/admin/download/12/23d2fff7f606e93acac9ede5b4e2b394.png will trigger the route_in_bundle_b first and the routes that doesn't have the download segment will not trigger it and will trigger the route_in_bundle_a rule.

Optional Prefix part in Route

I'm trying to create a rather complex-route schema and I'm stuck.
Routes that I wan't to match
/books indexAction
/books/show showAction
/books/authorname indexAction
/books/authorname/show showAction
Current Setup
Routing.yml
actions:
resource: routing/actions.yml
prefix: /books/{authorname}
requirements:
authorname: ".*"
defaults:
authorname: ''
routing/actions.yml
books_index:
path: ""
defaults: { _controller:bookController:indexAction }
books_show:
path: "/show"
defaults: { _controller:bookController:showAction }
This Setup currently matches only:
/books/ indexAction
/books/show showAction
/books/authorname indexAction
/books/authorname/show showAction
but not
/books
The reasons why I split those routes into two files is that in reality the actions contain much more routes, also there is other routing-categories then the actions.
I know I could define the /books route manually without a prefix but I want to avoid this as this schema will be used for many different modules.
You need a /book prefix in any case.
One solution is to define separate entries in your routing.yml for that. One with /books prefix and the second with /books/{authorname}.
index:
resource: routing/actions.yml
prefix: /books
show:
resource: routing/actions.yml
prefix: /books/{authorname}
It's not so elegant, but in this case you can get rid of extra requirements section.
Hope this helps!

Symfony2 route based on host. With parameters

I have followed the instructions here:
http://symfony.com/doc/current/components/routing/hostname_pattern.html
To make the route based on the host. However I want to use parameters instead of hard coding. The documentation says you can use service parameters, but I seem to be having trouble getting the parameters to work.
Here is the code from routing.yml:
rc_course_new:
pattern: /course/new
host: "{ domain }"
defaults: { _controller: CoursesRCWizardBundle:Wizard:new }
requirements:
domain: "%rc_domain%"
And here is the code from services.yml:
parameters:
rc_domain: my.domain.com
I get this error (looks like it is not picking up the parameter but seeing it as a hard code):
Oops! Google Chrome could not find { domain }
Managed to fix this:
In the routing:
rc_course_new:
pattern: /course/new
host: "%rc_domain%"
defaults: { _controller: CoursesRCWizardBundle:Wizard:new }
In the services (might work better in the parameters file) file:
parameters:
rc_domain: my.domain.com

Use array from parameters.yml in routing.yml

I got a locales declaration in my parameters.yml
parameters:
locale: en
locales: [ en, de, fr, it, es, pt, ru, ja, zh ]
and want to reuse the locales param in routing.yml
homepage_locale:
pattern: /{_locale}
defaults: { _controller: SiteBundle:World:index }
requirements: { _locale: %locales% }
But this obviously results in
The container parameter "locales", used in the route configuration value
"%locales%", must be a string or numeric, but it is of type array.
Is there a way to reuse this param or do I really have to write the locales as a string to satisfy this yaml/regex format, like this:
en|de|fr|it|es|pt|ru|ja|zh
In src/AppBundle/DependencyInjection/AppExtension.php
you can add in load function this code
$languages = $container->getParameter('languages');
$container->setParameter('languages_string', implode('|', $languages));
Then you will can use in your annotation
* requirements={"_locale": "%languages_string%"},
It prevent from duplicate parameters in your config file.
What about it:
parameters:
locale: en
locales: en|de|fr|it|es|pt|ru|ja|zh
Maybe you must try
_locale: en|de|fr|it|es|pt|ru|ja|zh
Good look

Route with optional parameter is not working in Symfony 2

I am experiencing some issues with optional parameters in my routes. I think I did it properly according to the documentation but still it is not working.
So I have the following route defined:
test_wizard:
pattern: /test/wizard/{testName}/{step}/
defaults: { _controller: TestBundle:Wizard:wizard, step: 1 }
and would like the route to be able to be called by /test/wizard/someTestName and then fill in the step parameter with the default value of 1 but everytime I call the route just with the test name I get the following instead:
No route found for "GET /test/wizard/someTestName"
When I call the route by /test/wizard/someTestName/1/ itworks just fine. Why is my defined default value for step not working? Any suggestions? Thanks.
It is not possible to make a parameter optional if you have a character after it (/ in your case). You have to define two routes:
test_wizard:
pattern: /test/wizard/{testName}
defaults: { _controller: TestBundle:Wizard:wizard }
test_wizard_optional:
pattern: /test/wizard/{testName}/{step}/
defaults: { _controller: TestBundle:Wizard:wizard, step: 1 }

Resources