1.3 version
Maintained Unmaintained


At the core of the Symfony CMF Routing component sits the ChainRouter. It is used as a replacement for Symfony’s default routing system.

The ChainRouter works by accepting a set of prioritized routing strategies, Symfony\Component\Routing\RouterInterface implementations, commonly referred to as “routers”.

When handling an incoming request, the ChainRouter iterates over the configured routers, sorted by their configured priority, until one of them is able to match the request or to match the URL and provide the request parameters.


Historically, the router had to do the matching on the URL string alone. Since Symfony 2.2, it can alternatively implement the RequestMatcherInterface to do the matching on the full Symfony\Component\HttpFoundation\Request object if it wants to use other request information into account like the domain or accept-encoding. The ChainRouter supports both types of route matching.

Adding Routers to the Chain

Routers are added using the add method of the ChainRouter. Use this to add the default Symfony router:

use Symfony\Component\Routing\Router;
use Symfony\Cmf\Component\Routing\ChainRouter;

$chainRouter = new ChainRouter();
$chainRouter->add(new Router(...));

Now, when the ChainRouter matches a request, it will ask the Symfony Router to see if the request matches. If there is no match, it will throw a Symfony\Component\Routing\Exception\ResourceNotFoundException.

If you add a new router, for instance the DynamicRouter, it will be called after the Symfony Router (because that was added first). To control the order, you can use the second argument of the add method to set a priority. Higher priorities are sorted first.

use Symfony\Cmf\Component\Routing\DynamicRouter;
// ...

$chainRouter->add(new Router(...), 1);

$dynamicRouter = new DynamicRouter(...);
// ...
$chainRouter->add($dynamicRouter, 100);


You’ll learn how to instantiate the DynamicRouter later in this article.

Register Routers Compiler Pass

This component provides a RegisterRoutersPass. If you use the Symfony Dependency Injection Component, you can use this compiler pass to register all routers with a specific tag:

use Symfony\Cmf\Component\Routing\DependencyInjection\Compiler\RegisterRoutersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

// a ContainerBuilder
$container = ...;

$pass = new RegisterRoutersPass('cmf_routing.router', 'router');

After adding the passes and configuring the container builder, you continue with compiling the container as explained in the Symfony DI Component compilation section.

You can optionally configure the chain router service name. The compiler pass will modify this service definition to register the routers when the chain router is loaded from the container. If you do not specify anything, the service name is cmf_routing.router.

You can also configure the tag name you want to use with the second argument to the compiler pass constructor. If you don’t, the default tag is router. If you are using the Symfony CMF RoutingBundle, this tag is already active with the default name.


The ChainRouter is incapable of, by itself, making any actual routing decisions. Its sole responsibility is managing the given set of Routers, which are responsible for matching a request and determining its parameters.

You can easily create your own routers by implementing Symfony\Component\Routing\RouterInterface but the Symfony CMF Routing Component already includes a powerful route matching system that you can extend to your needs.

Symfony Default Router

The Symfony routing mechanism is itself a RouterInterface implementation, which means you can use it as a Router in the ChainRouter. This allows you to use the default routing declaration system. Read more about this router in the Routing Component article of the core documentation.

Dynamic Router

The dynamic router is best added with a lower priority, as the default router is faster in taking routing decisions.

Read on about the dynamic router in the next section.

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