Kid Binary Kid Binary - 2 months ago 26
PHP Question

Symfony routing - locale as subdomain with fallback to default

I'm trying to set up routing system with subdomain representing current locale. Routing is set via

@Routing
annotation and looks like this:

/**
* @Route(
* "/",
* name="homepage",
* host="{locale}.{domain}",
* defaults={"locale" = "en", "domain" = "%domain%"},
* requirements={"locale" = "en|de|fr", "domain" = "%domain%"}
* )
*/


Works well for URL's like
en.somedomain.com
or
de.somedomain.com
, but fails to find correct route for
somedomain.com
, without locale.

I understand that because of the
host
parameter, that is set to represent exact locale.domain pattern, but I can't find way to tell Symfony routing system that there could be additional, default
host
.

Searched all around for this, but found nothing particular. Would appreciate any help!

UPDATE

There is actually a way to do it, by adding another
@Route
in annotation, without
host
parameter:

/**
* @Route(
* "/",
* name="homepage_default",
* defaults={"locale" = "en"}
* )
*/


but thats looks a bit dirty, and I'm not using
%domain%
parameter there, which is important for me - say, if I would need another subdomain for mobile version.

Answer

Well, looks like triple annotation routing to handle locale + subdomain is the only choice for now.

Studying documentation (for example, this article) shows that Symfony developers encourage us to do it that way, which, to me, is not that nice. However, here's the solution...

/**
 * @Method({"GET"})
 * @Route(
 *      "/",
 *      name="homepage",
 *      host="{mobile}.{_locale}.{domain}",
 *      defaults={"mobile" = "moblie", "locale" = "%locale%", "domain" = "%domain%"},
 *      requirements={"mobile" = "mobile|m", "_locale" = "%locale%|de|fr",  "domain" = "%domain%"}
 * )
 * @Route(
 *      "/",
 *      name="homepage",
 *      host="{_locale}.{domain}",
 *      defaults={"_locale" = "%locale%", "domain" = "%domain%"},
 *      requirements={"_locale" = "%locale%|de|fr", "domain" = "%domain%"}
 * )
 * @Route(
 *      "/",
 *      name="homepage_default",
 *      defaults={"_locale" = "%locale%"}
 * )
 */

Notice that order is important, starting from subdomains, going down to default. As this looks ugly with @Route annotation, I've decided to re-write this in YAML as well:

homepage_locale_mobile:
    path:      /
    host:      "{mobile}.{_locale}.{domain}"
    defaults:  { mobile: "mobile", _locale: "%locale%", domain: "%domain%" }
    requirements:
        mobile:  "mobile|m"
        _locale: "%locale%|de|fr",
        domain:  "%domain%"

homepage_locale:
    path:      /
    host:      "{_locale}.{domain}"
    defaults:  { _locale: "%locale%", domain: "%domain%" }
    requirements:
        _locale: "%locale%|de|fr",
        domain:  "%domain%"

homepage:
    path:      /
    defaults:  { _locale: "%locale%" }

Ordered as well. Maybe someone will come across and use it.