You are browsing the Symfony 4 documentation, which changes significantly from Symfony 3.x. If your app doesn't use Symfony 4 yet, browse the Symfony 3.4 documentation.

How to Use Service Container Parameters in your Routes

4.4 version

How to Use Service Container Parameters in your Routes

Sometimes you may find it useful to make some parts of your routes globally configurable. For instance, if you build an internationalized site, you'll probably start with one or two locales. Surely you'll add a requirement to your routes to prevent a user from matching a locale other than the locales you support.

You could hardcode your _locale requirement in all your routes, but a better solution is to use a configurable service container parameter right inside your routing configuration:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // src/Controller/MainController.php
    namespace App\Controller;
    
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\Routing\Annotation\Route;
    
    class MainController extends AbstractController
    {
        /**
         * @Route("/{_locale}/contact", name="contact", requirements={
         *     "_locale"="%app.locales%"
         * })
         */
        public function contact()
        {
            // ...
        }
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    # config/routes.yaml
    contact:
        path:       /{_locale}/contact
        controller: App\Controller\MainController::contact
        requirements:
            _locale: '%app.locales%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- 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
            https://symfony.com/schema/routing/routing-1.0.xsd">
    
        <route id="contact" path="/{_locale}/contact" controller="App\Controller\MainController::contact">
            <requirement key="_locale">%app.locales%</requirement>
        </route>
    </routes>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    // config/routes.php
    use App\Controller\MainController;
    use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
    
    return function (RoutingConfigurator $routes) {
        $routes->add('contact', '/{_locale}/contact')
            ->controller([MainController::class, 'contact'])
            ->requirements([
                '_locale' => '%app.locales%',
            ])
        ;
    };
    

You can now control and set the app.locales parameter somewhere in your container:

  • YAML
    1
    2
    3
    # config/services.yaml
    parameters:
        app.locales: en|es
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- config/services.xml -->
    <?xml version="1.0" charset="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="app.locales">en|es</parameter>
        </parameters>
    </container>
    
  • PHP
    1
    2
    // config/services.php
    $container->setParameter('app.locales', 'en|es');
    

You can also use a parameter to define your route path (or part of your path):

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    // src/Controller/MainController.php
    namespace App\Controller;
    
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\Routing\Annotation\Route;
    
    class MainController extends AbstractController
    {
        /**
         * @Route("/%app.route_prefix%/contact", name="contact")
         */
        public function contact()
        {
            // ...
        }
    }
    
  • YAML
    1
    2
    3
    4
    # config/routes.yaml
    some_route:
        path:       /%app.route_prefix%/contact
        controller: App\Controller\MainController::contact
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- 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
            https://symfony.com/schema/routing/routing-1.0.xsd">
    
        <route id="some_route"
            path="/%app.route_prefix%/contact"
            controller="App\Controller\MainController::contact"/>
    </routes>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // config/routes.php
    use App\Controller\MainController;
    use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
    
    return function (RoutingConfigurator $routes) {
        $routes->add('contact', '/%app.route_prefix%/contact')
            ->controller([MainController::class, 'contact'])
        ;
    };
    

Now make sure that the app.route_prefix parameter is set somewhere in your container:

  • YAML
    1
    2
    3
    # config/services.yaml
    parameters:
        app.route_prefix: 'foo'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- config/services.xml -->
    <?xml version="1.0" charset="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="app.route_prefix">foo</parameter>
        </parameters>
    </container>
    
  • PHP
    1
    2
    // config/services.php
    $container->setParameter('app.route_prefix', 'foo');
    

Note

Just like in normal service container configuration files, if you actually need a % in your route, you can escape the percent sign by doubling it, e.g. /score-50%%, which would resolve to /score-50%.

However, as the % characters included in any URL are automatically encoded, the resulting URL of this example would be /score-50%25 (%25 is the result of encoding the % character).

For parameter handling within a Dependency Injection Class see Using Parameters within a Dependency Injection Class.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.