Symfony2: An alternative to Symfony 1′s “routing.load_configuration” event

Important note: the solution provided here is not right. Please read my other post on this, in which I reveal the right solution for this problem.

Symfony 1 had the lovely routing.load_configuration event. Listening to this event enabled the developer to add some routes dynamically, “on-the-fly”. Plugins used to do this most of the time. I was looking for a way to accomplish the same in Symfony 2. I’ve used the following as a solution.

We are going to listen to the kernel.request event, but we make sure we get notified in an early stage, so that the router hasn’t done it’s magic yet. Then we quickly add some extra routes to the RouteCollection.

Create a routing listener

First we need an event listener, let’s call it RoutingListener. The router will be injected by defining this dependency in the service’s definition (see below). onEarlyKernelRequest will be the method that responds to the kernel.request event and adds an extra route to the router’s route collection:

// in src/Acme/DemoBundle/EventListener/RoutingListener.php

namespace Acme\DemoBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;

use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Routing\Route;

class RoutingListener
{
    protected $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    public function onEarlyKernelRequest(GetResponseEvent $event)
    {
        // create a new route; other arguments would be an
        // array containing requirements and an array with options
        $route = new Route('/welcome-to-symfony2', array(
            '_controller' => 'AcmeDemoBundle:Welcome:index',
        ));

        $this->router->getRouteCollection()->add('extraRoute', $route);
    }
}

Now we should announce the existence of this listener to the kernel itself. We can do this by defining the listener as a service in /src/Acme/DemoBundle/Resources/services.xml:

<?xml version="1.0" ?>
<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 http://symfony.com/schema/dic/services/services-1.0.xsd">
    <services>
        <!-- ... --->

        <service id="acme.routing_listener" class="Acme\DemoBundle\EventListener\RoutingListener">
            <argument type="service" id="router" />
            <tag name="kernel.event_listener" event="kernel.request" method="onEarlyKernelRequest" priority="255" />
        </service>

    </services>
</container>

I wonder which value is really appropriate for “priority”, but at least this one works.

As you can see, we register the service using the tag “kernel.event_listener” as a service which responds to the kernel event kernel.request. Upon this event, the onEarlyKernelRequest should be fired and this adds the extra route. The service has one dependency, namely the router, which will be injected as the first argument of the constructor.

Test the setup by browsing to /app_dev.php/welcome-to-symfony2. You should now see the welcome page of your Symfony2 installation.

Nice, but…

Your newly added routes won’t appear in the output of the console command router:debug, since the kernel.request only gets fired for web applications. Nevertheless, the WebProfilerExtraBundle shows all the routes correctly. (You might even ask if a router:debug command actually is an appropriate console command, since routing is a typical “web” thing, but I admit it may be a little annoying that these “on-the-fly” created routes don’t appear in the list.)

Posted in Configuration, Events, Request, Routing, Service, Symfony2 | 5 Comments

5 Responses to Symfony2: An alternative to Symfony 1′s “routing.load_configuration” event

  • # December 6, 2011 at 02:49

    Hi Matthias.

    Nice post. I’ve tried to do what you said, but I’m getting a “No route found” error.
    I’ve tried to debug the route collection and everything looks ok – The route is there. Any idea?

    Note: When debugging the route collection I’ve noticed that all routes have the _controller like: “Bundle\FooBundle\Controller\FooController::fooAction”. And, the route created as you’re saying above appear like “BundleFooBundle:Foo:foo” – strange?

    Cheers,
    Maria

    Maria Lansole

    Reply

    • # December 15, 2011 at 12:36

      Thanks! I have not found any problem with this yet, though it is strange that both alternatives work (using the short or the long notation for controllers). Possibly this has something to do with different versions of Symfony2. I will try that later. Bye!

      Matthias Noback

      Reply

    • # January 3, 2012 at 21:22

      Okay, so I have completely redone this and the result is a new post, see http://php-and-symfony.matthiasnoback.nl/2012/01/symfony2-dynamically-add-routes/ Good luck!

      Matthias Noback

      Reply

  • # January 1, 2012 at 17:48

    Hi Matthias,
    I’m getting a “No route found” error same as Maria . my sf version is 2.0.8.
    Your articles are so awesome,thanks your hard work.

    andrew

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

* *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>