.. index::
single: Routing; Matching on Hostname
How to Match a Route Based on the Host
======================================
.. versionadded:: 2.2
Host matching support was introduced in Symfony 2.2
You can also match on the HTTP *host* of the incoming request.
.. configuration-block::
.. code-block:: yaml
mobile_homepage:
path: /
host: m.example.com
defaults: { _controller: AcmeDemoBundle:Main:mobileHomepage }
homepage:
path: /
defaults: { _controller: AcmeDemoBundle:Main:homepage }
.. code-block:: xml
AcmeDemoBundle:Main:mobileHomepage
AcmeDemoBundle:Main:homepage
.. code-block:: php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('mobile_homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:mobileHomepage',
), array(), array(), 'm.example.com'));
$collection->add('homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:homepage',
)));
return $collection;
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:
.. configuration-block::
.. code-block:: yaml
projects_homepage:
path: /
host: "{project_name}.example.com"
defaults: { _controller: AcmeDemoBundle:Main:mobileHomepage }
homepage:
path: /
defaults: { _controller: AcmeDemoBundle:Main:homepage }
.. code-block:: xml
AcmeDemoBundle:Main:mobileHomepage
AcmeDemoBundle:Main:homepage
.. code-block:: php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('project_homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:mobileHomepage',
), array(), array(), '{project_name}.example.com'));
$collection->add('homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:homepage',
)));
return $collection;
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:
.. configuration-block::
.. code-block:: yaml
mobile_homepage:
path: /
host: "{subdomain}.example.com"
defaults:
_controller: AcmeDemoBundle:Main:mobileHomepage
subdomain: m
requirements:
subdomain: m|mobile
homepage:
path: /
defaults: { _controller: AcmeDemoBundle:Main:homepage }
.. code-block:: xml
AcmeDemoBundle:Main:mobileHomepage
m
m|mobile
AcmeDemoBundle:Main:homepage
.. code-block:: php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('mobile_homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:mobileHomepage',
'subdomain' => 'm',
), array(
'subdomain' => 'm|mobile',
), array(), '{subdomain}.example.com'));
$collection->add('homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:homepage',
)));
return $collection;
.. tip::
You can also use service parameters if you do not want to hardcode the
hostname:
.. configuration-block::
.. code-block:: yaml
mobile_homepage:
path: /
host: "m.{domain}"
defaults:
_controller: AcmeDemoBundle:Main:mobileHomepage
domain: "%domain%"
requirements:
domain: "%domain%"
homepage:
path: /
defaults: { _controller: AcmeDemoBundle:Main:homepage }
.. code-block:: xml
AcmeDemoBundle:Main:mobileHomepage
%domain%
%domain%
AcmeDemoBundle:Main:homepage
.. code-block:: php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('mobile_homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:mobileHomepage',
'domain' => '%domain%',
), array(
'domain' => '%domain%',
), array(), 'm.{domain}'));
$collection->add('homepage', new Route('/', array(
'_controller' => 'AcmeDemoBundle:Main:homepage',
)));
return $collection;
.. 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.
.. _component-routing-host-imported:
Using Host Matching of Imported Routes
--------------------------------------
You can also set the host option on imported routes:
.. configuration-block::
.. code-block:: yaml
# app/config/routing.yml
acme_hello:
resource: "@AcmeHelloBundle/Resources/config/routing.yml"
host: "hello.example.com"
.. code-block:: xml
.. code-block:: php
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
$collection = new RouteCollection();
$collection->addCollection($loader->import("@AcmeHelloBundle/Resources/config/routing.php"), '', array(), array(), array(), 'hello.example.com');
return $collection;
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.
.. code-block:: php
$crawler = $client->request(
'GET',
'/homepage',
array(),
array(),
array('HTTP_HOST' => 'm.' . $client->getContainer()->getParameter('domain'))
);