How to Match a Route Based on the Host
Warning: You are browsing the documentation for Symfony 2.x, which is no longer maintained.
Read the updated version of this page for Symfony 7.1 (the current stable version).
You can also match on the HTTP host of the incoming request.
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/Acme/DemoBundle/Controller/MainController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class MainController extends Controller
{
/**
* @Route("/", name="mobile_homepage", host="m.example.com")
*/
public function mobileHomepageAction()
{
// ...
}
/**
* @Route("/", name="homepage")
*/
public function homepageAction()
{
// ...
}
}
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:
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/Acme/DemoBundle/Controller/MainController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class MainController extends Controller
{
/**
* @Route("/", name="projects_homepage", host="{project_name}.example.com")
*/
public function projectsHomepageAction()
{
// ...
}
/**
* @Route("/", name="homepage")
*/
public function homepageAction()
{
// ...
}
}
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:
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/Acme/DemoBundle/Controller/MainController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class MainController extends Controller
{
/**
* @Route(
* "/",
* name="mobile_homepage",
* host="{subdomain}.example.com",
* defaults={"subdomain"="m"},
* requirements={"subdomain"="m|mobile"}
* )
*/
public function mobileHomepageAction()
{
// ...
}
/**
* @Route("/", name="homepage")
*/
public function homepageAction()
{
// ...
}
}
Tip
You can also use service parameters if you do not want to hardcode the hostname:
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/Acme/DemoBundle/Controller/MainController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class MainController extends Controller
{
/**
* @Route(
* "/",
* name="mobile_homepage",
* host="m.{domain}",
* defaults={"domain"="%domain%"},
* requirements={"domain"="%domain%"}
* )
*/
public function mobileHomepageAction()
{
// ...
}
/**
* @Route("/", name="homepage")
*/
public function homepageAction()
{
// ...
}
}
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:
1 2 3 4 5 6 7 8 9 10 11 12 13
// src/Acme/HelloBundle/Controller/MainController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
/**
* @Route(host="hello.example.com")
*/
class MainController extends Controller
{
// ...
}
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:
1 2 3 4 5 6 7
$crawler = $client->request(
'GET',
'/homepage',
array(),
array(),
array('HTTP_HOST' => 'm.' . $client->getContainer()->getParameter('domain'))
);