You are browsing the documentation for Symfony 4.1 which is not maintained anymore.
Consider upgrading your projects to Symfony 5.2.
How to Match a Route Based on the Host
How to Match a Route Based on the Host¶
You can also match on the HTTP host of the incoming request.
- Annotations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/Controller/MainController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class MainController extends AbstractController { /** * @Route("/", name="mobile_homepage", host="m.example.com") */ public function mobileHomepage() { // ... } /** * @Route("/", name="homepage") */ public function homepage() { // ... } }
- YAML
1 2 3 4 5 6 7 8 9
# config/routes.yaml mobile_homepage: path: / host: m.example.com controller: App\Controller\MainController::mobileHomepage homepage: path: / controller: App\Controller\MainController::homepage
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<!-- config/routes.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="mobile_homepage" path="/" host="m.example.com"> <default key="_controller">App\Controller\MainController::mobileHomepage</default> </route> <route id="homepage" path="/"> <default key="_controller">App\Controller\MainController::homepage</default> </route> </routes>
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $routes = new RouteCollection(); $routes->add('mobile_homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::mobileHomepage', ], [], [], 'm.example.com')); $routes->add('homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::homepage', ])); return $routes;
Both routes match the same path /
, however the first one will match
only if the host is m.example.com
.
Using Placeholders¶
The host option uses the same syntax as the path matching system. This means you can use placeholders in your hostname:
- Annotations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/Controller/MainController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class MainController extends AbstractController { /** * @Route("/", name="projects_homepage", host="{project_name}.example.com") */ public function projectsHomepage() { // ... } /** * @Route("/", name="homepage") */ public function homepage() { // ... } }
- YAML
1 2 3 4 5 6 7 8 9
# config/routes.yaml projects_homepage: path: / host: "{project_name}.example.com" controller: App\Controller\MainController::projectsHomepage homepage: path: / controller: App\Controller\MainController::homepage
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<!-- config/routes.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="projects_homepage" path="/" host="{project_name}.example.com"> <default key="_controller">App\Controller\MainController::projectsHomepage</default> </route> <route id="homepage" path="/"> <default key="_controller">App\Controller\MainController::homepage</default> </route> </routes>
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $routes = new RouteCollection(); $routes->add('project_homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::projectsHomepage', ], [], [], '{project_name}.example.com')); $routes->add('homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::homepage', ])); return $routes;
You can also set requirements and default options for these placeholders. For
instance, if you want to match both m.example.com
and
mobile.example.com
, you use this:
- Annotations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// src/Controller/MainController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class MainController extends AbstractController { /** * @Route( * "/", * name="mobile_homepage", * host="{subdomain}.example.com", * defaults={"subdomain"="m"}, * requirements={"subdomain"="m|mobile"} * ) */ public function mobileHomepage() { // ... } /** * @Route("/", name="homepage") */ public function homepage() { // ... } }
- YAML
1 2 3 4 5 6 7 8 9 10 11 12 13
# config/routes.yaml mobile_homepage: path: / host: "{subdomain}.example.com" controller: App\Controller\MainController::mobileHomepage defaults: subdomain: m requirements: subdomain: m|mobile homepage: path: / controller: App\Controller\MainController::homepage
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<!-- config/routes.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="mobile_homepage" path="/" host="{subdomain}.example.com"> <default key="_controller">App\Controller\MainController::mobileHomepage</default> <default key="subdomain">m</default> <requirement key="subdomain">m|mobile</requirement> </route> <route id="homepage" path="/"> <default key="_controller">App\Controller\MainController::homepage</default> </route> </routes>
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $routes = new RouteCollection(); $routes->add('mobile_homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::mobileHomepage', 'subdomain' => 'm', ], [ 'subdomain' => 'm|mobile', ], [], '{subdomain}.example.com')); $routes->add('homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::homepage', ])); return $routes;
Tip
You can also use service parameters if you do not want to hardcode the hostname:
- Annotations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// src/Controller/MainController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class MainController extends AbstractController { /** * @Route( * "/", * name="mobile_homepage", * host="m.{domain}", * defaults={"domain"="%domain%"}, * requirements={"domain"="%domain%"} * ) */ public function mobileHomepage() { // ... } /** * @Route("/", name="homepage") */ public function homepage() { // ... } }
- YAML
1 2 3 4 5 6 7 8 9 10 11 12 13
# config/routes.yaml mobile_homepage: path: / host: "m.{domain}" controller: App\Controller\MainController::mobileHomepage defaults: domain: '%domain%' requirements: domain: '%domain%' homepage: path: / controller: App\Controller\MainController::homepage
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<!-- config/routes.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="mobile_homepage" path="/" host="m.{domain}"> <default key="_controller">App\Controller\MainController::mobileHomepage</default> <default key="domain">%domain%</default> <requirement key="domain">%domain%</requirement> </route> <route id="homepage" path="/"> <default key="_controller">App\Controller\MainController::homepage</default> </route> </routes>
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $routes = new RouteCollection(); $routes->add('mobile_homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::mobileHomepage', 'domain' => '%domain%', ], [ 'domain' => '%domain%', ], [], 'm.{domain}')); $routes->add('homepage', new Route('/', [ '_controller' => 'App\Controller\MainController::homepage', ])); return $routes;
Tip
Make sure you also include a default option for the domain
placeholder,
otherwise you need to include a domain value each time you generate
a URL using the route.
Using Host Matching of Imported Routes¶
You can also set the host option on imported routes:
- Annotations
1 2 3 4 5 6 7 8 9 10 11 12 13
// src/Controller/MainController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; /** * @Route(host="hello.example.com") */ class MainController extends AbstractController { // ... }
- YAML
1 2 3 4
# config/routes.yaml app_hello: resource: '@ThirdPartyBundle/Resources/config/routing.yaml' host: "hello.example.com"
- XML
1 2 3 4 5 6 7 8 9
<!-- config/routes.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <import resource="@ThirdPartyBundle/Resources/config/routing.xml" host="hello.example.com" /> </routes>
- PHP
1 2 3 4 5
// config/routes.php $routes = $loader->import("@ThirdPartyBundle/Resources/config/routing.php"); $routes->setHost('hello.example.com'); return $routes;
The host hello.example.com
will be set on each route loaded from the new
routing resource.
Testing your Controllers¶
You need to set the Host HTTP header on your request objects if you want to get past url matching in your functional tests:
$crawler = $client->request(
'GET',
'/homepage',
[],
[],
['HTTP_HOST' => 'm.' . $client->getContainer()->getParameter('domain')]
);
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.