.. index:: single: Routing; Conditions
A route can be made to match only certain routing placeholders (via regular
expressions), HTTP methods, or host names. If you need more flexibility to
define arbitrary matching logic, use the conditions
routing option:
.. configuration-block:: .. code-block:: php-annotations // src/Controller/DefaultController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class DefaultController extends AbstractController { /** * @Route( * "/contact", * name="contact", * condition="context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'" * ) * * expressions can also include config parameters * condition: "request.headers.get('User-Agent') matches '%app.allowed_browsers%'" */ public function contact() { // ... } } .. code-block:: yaml # config/routes.yaml contact: path: /contact controller: 'App\Controller\DefaultController::contact' condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'" # expressions can also include config parameters # condition: "request.headers.get('User-Agent') matches '%app.allowed_browsers%'" .. code-block:: xml <!-- 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="contact" path="/contact"> <default key="_controller">App\Controller\DefaultController::contact</default> <condition>context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'</condition> <!-- expressions can also include config parameters --> <!-- <condition>request.headers.get('User-Agent') matches '%app.allowed_browsers%'</condition> --> </route> </routes> .. code-block:: php // config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $routes = new RouteCollection(); $routes->add('contact', new Route( '/contact', [ '_controller' => 'App\Controller\DefaultController::contact', ], [], [], '', [], [], 'context.getMethod() in ["GET", "HEAD"] and request.headers.get("User-Agent") matches "/firefox/i"' // expressions can also include config parameters // 'request.headers.get("User-Agent") matches "%app.allowed_browsers%"' )); return $collection;
The condition
is an expression, and you can learn more about its syntax
here: :doc:`/components/expression_language/syntax`. With this, the route
won't match unless the HTTP method is either GET or HEAD and if the User-Agent
header matches firefox
.
You can do any complex logic you need in the expression by leveraging two variables that are passed into the expression:
context
- An instance of :class:`Symfony\\Component\\Routing\\RequestContext`, which holds the most fundamental information about the route being matched.
request
- The Symfony :class:`Symfony\\Component\\HttpFoundation\\Request` object (see :ref:`component-http-foundation-request`).
Caution!
Conditions are not taken into account when generating a URL.
Expressions are Compiled to PHP
Behind the scenes, expressions are compiled down to raw PHP. Our example would generate the following PHP in the cache directory:
if (rtrim($pathInfo, '/contact') === '' && ( in_array($context->getMethod(), [0 => "GET", 1 => "HEAD"]) && preg_match("/firefox/i", $request->headers->get("User-Agent")) )) { // ... }
Because of this, using the condition
key causes no extra overhead
beyond the time it takes for the underlying PHP to execute.