Symfony
sponsored by SensioLabs
Menu
  • About
  • Documentation
  • Screencasts
  • Cloud
  • Certification
  • Community
  • Businesses
  • News
  • Download
  1. Home
  2. Documentation
  3. Routing
  4. How to Define Route Requirements
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud
Search by Algolia

Table of Contents

  • Adding HTTP Method Requirements
  • Adding a Host Requirement
  • Adding Dynamic Requirements with Expressions

How to Define Route Requirements

Edit this page

Warning: You are browsing the documentation for Symfony 3.3, which is no longer maintained.

Read the updated version of this page for Symfony 6.2 (the current stable version).

How to Define Route Requirements

Route requirements can be used to make a specific route only match under specific conditions. The simplest example involves restricting a routing {wildcard} to only match some regular expression:

  • Annotations
  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/AppBundle/Controller/BlogController.php
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class BlogController extends Controller
{
    /**
     * @Route("/blog/{page}", name="blog_list", requirements={"page"="\d+"})
     */
    public function listAction($page)
    {
        // ...
    }
}
1
2
3
4
5
6
# app/config/routing.yml
blog_list:
    path:      /blog/{page}
    defaults:  { _controller: AppBundle:Blog:list }
    requirements:
        page: '\d+'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- app/config/routing.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="blog_list" path="/blog/{page}">
        <default key="_controller">AppBundle:Blog:list</default>
        <requirement key="page">\d+</requirement>
    </route>

    <!-- ... -->
</routes>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('blog_list', new Route('/blog/{page}', array(
    '_controller' => 'AppBundle:Blog:list',
), array(
    'page' => '\d+'
)));

// ...

return $collection;

Thanks to the \d+ requirement (i.e. a "digit" of any length), /blog/2 will match this route but /blog/some-string will not match.

Earlier Routes Always Win

Why would you ever care about requirements? If a request matches two routes, then the first route always wins. By adding requirements to the first route, you can make each route match in just the right situations. See Routing for an example.

Since the parameter requirements are regular expressions, the complexity and flexibility of each requirement is entirely up to you. Suppose the homepage of your application is available in two different languages, based on the URL:

  • Annotations
  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Controller/MainController.php

// ...
class MainController extends Controller
{
    /**
     * @Route("/{_locale}", defaults={"_locale"="en"}, requirements={
     *     "_locale"="en|fr"
     * })
     */
    public function homepageAction($_locale)
    {
    }
}
1
2
3
4
5
6
# app/config/routing.yml
homepage:
    path:      /{_locale}
    defaults:  { _controller: AppBundle:Main:homepage, _locale: en }
    requirements:
        _locale:  en|fr
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- app/config/routing.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="homepage" path="/{_locale}">
        <default key="_controller">AppBundle:Main:homepage</default>
        <default key="_locale">en</default>
        <requirement key="_locale">en|fr</requirement>
    </route>
</routes>
1
2
3
4
5
6
7
8
9
10
11
12
13
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('homepage', new Route('/{_locale}', array(
    '_controller' => 'AppBundle:Main:homepage',
    '_locale'     => 'en',
), array(
    '_locale' => 'en|fr',
)));

return $collection;

For incoming requests, the {_locale} portion of the URL is matched against the regular expression (en|fr).

Path Parameters
/ {_locale} = "en"
/en {_locale} = "en"
/fr {_locale} = "fr"
/es won't match this route

Note

Since Symfony 3.2, you can enable UTF-8 route matching by setting the utf8 option when declaring or importing routes. This will make e.g. a . in requirements match any UTF-8 characters instead of just a single byte. The option is automatically enabled whenever a route or a requirement uses any non-ASCII UTF-8 characters or a PCRE Unicode property (\p{xx}, \P{xx} or \X). Note that this behavior is deprecated and a LogicException will be thrown instead in 4.0 unless you explicitly turn on the utf8 option.

Tip

The route requirements can also include container parameters, as explained in this article. This comes in handy when the regular expression is very complex and used repeatedly in your application.

Adding HTTP Method Requirements

In addition to the URL, you can also match on the method of the incoming request (i.e. GET, HEAD, POST, PUT, DELETE). Suppose you create an API for your blog and you have 2 routes: One for displaying a post (on a GET or HEAD request) and one for updating a post (on a PUT request). This can be accomplished with the following route configuration:

  • Annotations
  • YAML
  • XML
  • PHP
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
// src/AppBundle/Controller/BlogApiController.php
namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
// ...

class BlogApiController extends Controller
{
    /**
     * @Route("/api/posts/{id}")
     * @Method({"GET","HEAD"})
     */
    public function showAction($id)
    {
        // ... return a JSON response with the post
    }

    /**
     * @Route("/api/posts/{id}")
     * @Method("PUT")
     */
    public function editAction($id)
    {
        // ... edit a post
    }
}
1
2
3
4
5
6
7
8
9
10
# app/config/routing.yml
api_post_show:
    path:     /api/posts/{id}
    defaults: { _controller: AppBundle:BlogApi:show }
    methods:  [GET, HEAD]

api_post_edit:
    path:     /api/posts/{id}
    defaults: { _controller: AppBundle:BlogApi:edit }
    methods:  [PUT]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- app/config/routing.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="api_post_show" path="/api/posts/{id}" methods="GET|HEAD">
        <default key="_controller">AppBundle:BlogApi:show</default>
    </route>

    <route id="api_post_edit" path="/api/posts/{id}" methods="PUT">
        <default key="_controller">AppBundle:BlogApi:edit</default>
    </route>
</routes>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('api_post_show', new Route('/api/posts/{id}', array(
    '_controller' => 'AppBundle:BlogApi:show',
), array(), array(), '', array(), array('GET', 'HEAD')));

$collection->add('api_post_edit', new Route('/api/posts/{id}', array(
    '_controller' => 'AppBundle:BlogApi:edit',
), array(), array(), '', array(), array('PUT')));

return $collection;

Despite the fact that these two routes have identical paths (/api/posts/{id}), the first route will match only GET or HEAD requests and the second route will match only PUT requests. This means that you can display and edit the post with the same URL, while using distinct controllers for the two actions.

Note

If no methods are specified, the route will match on all methods.

Tip

If you're using HTML forms and HTTP methods other than GET and POST, you'll need to include a _method parameter to fake the HTTP method. See How to Change the Action and Method of a Form for more information.

Adding a Host Requirement

You can also match on the HTTP host of the incoming request. For more information, see How to Match a Route Based on the Host in the Routing component documentation.

Adding Dynamic Requirements with Expressions

For really complex requirements, you can use dynamic expressions to match any information on the request. See How to Restrict Route Matching through Conditions.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
We stand with Ukraine.
Version:
Measure & Improve Symfony Code Performance

Measure & Improve Symfony Code Performance

Code consumes server resources. Blackfire tells you how

Code consumes server resources. Blackfire tells you how

↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

Avatar of Denis Rendler, a Symfony contributor

Thanks Denis Rendler for being a Symfony contributor

11 commits • 35 lines changed

View all contributors that help us make Symfony

Become a Symfony contributor

Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

Learn how to contribute

Symfony™ is a trademark of Symfony SAS. All rights reserved.

  • What is Symfony?
    • Symfony at a Glance
    • Symfony Components
    • Case Studies
    • Symfony Releases
    • Security Policy
    • Logo & Screenshots
    • Trademark & Licenses
    • symfony1 Legacy
  • Learn Symfony
    • Symfony Docs
    • Symfony Book
    • Reference
    • Bundles
    • Best Practices
    • Training
    • eLearning Platform
    • Certification
  • Screencasts
    • Learn Symfony
    • Learn PHP
    • Learn JavaScript
    • Learn Drupal
    • Learn RESTful APIs
  • Community
    • SymfonyConnect
    • Support
    • How to be Involved
    • Code of Conduct
    • Events & Meetups
    • Projects using Symfony
    • Downloads Stats
    • Contributors
    • Backers
  • Blog
    • Events & Meetups
    • A week of symfony
    • Case studies
    • Cloud
    • Community
    • Conferences
    • Diversity
    • Documentation
    • Living on the edge
    • Releases
    • Security Advisories
    • SymfonyInsight
    • Twig
    • SensioLabs
  • Services
    • SensioLabs services
    • Train developers
    • Manage your project quality
    • Improve your project performance
    • Host Symfony projects
    Deployed on
Follow Symfony
Search by Algolia