Modular Routing in Symfony

Found a typo? Edit me
This post is deprecated since June 2017. Its knowledge is old and should not be used.
Why?

I have deprecated this package, because of feedback that it is not useful and low download rates (under 2 000 in 2 years).

You can use annotation routing in combination with PSR-4 controller autodiscovery since Symfony 3.3 and with routing annotation loader enabled by default since Symfony 3.4.

This package is still available here for inspiration though.


Modular routing in Symfony is bounded to routing.yml. Adding few lines for each new module can create large mess. Can we make it bit simpler? Sure we do and I will show you how.

Let's say you have fairly standalone module or package and you want to add its routes as simple as:

// app/AppKernel.php

final class AppKernel extends Kernel
{
    public function registerBundles(): array
    {
        $bundles = [
            new App\MeetupModule\AppMeetupModuleBundle(),
            // ...
        ];
    }
}

So, what you can do?


Wow, so many options!
Wow, so many options!


As Matthias Noback wrote 4 years ago, in Symfony 1 you could use routing.load_configuration event to do this, but it was removed in Symfony 2. As a replacement, Matthias suggests creating custom Route Loader. It's the best solution so far I used before.

But I'm older and more lazy now so I tried to find a simpler way.

Warning!
If you prefer YAML, XML or PHP definition, good news - continue.
In case you use @Route annotation, following solution won't help you.

Load your routes in 1 method

Routes are usually in form of a simple array with urlcontroller records.

What if loading of this simple array could be done via simple service? Something as simple as:

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

public function getRouteCollection(): RouteCollection
{
    return $this->loadRouteCollectionFromFile(__DIR__ . '/routes.yml');

    // OR xml
    return $this->loadRouteCollectionFromFile(__DIR__ . '/routes.xml');

    // OR even multiple files
    return $this->loadRouteCollectionFromFiles([
        __DIR__ . '/front_routes.yml',
        __DIR__ . '/admin_routes.yml'
    ]);

    // OR pure PHP with some tweaks
    $routeCollection = new RouteCollection();
    $routeCollection->add('my_route', new Route('/hello'));

    return $routeCollection;
}

Load your routes in modular way in 4 steps

All those options above are available in Symfony, thanks to Symplify\ModularRouting package.

Let's try it together.

1. Install package

composer require symplify/modular-routing

2. Register bundles

// app/AppKernel.php
final class AppKernel extends Kernel
{
    public function registerBundles(): array
    {
        return [
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Cmf\Bundle\RoutingBundle\CmfRoutingBundle(),
            new Symplify\ModularRouting\SymplifyModularRoutingBundle(),
            // ...
        ];
    }
}

3. Create services to load your YAML file

// src/SomeBundle/Routing/SomeRouteCollectionProvider.php
namespace SomeBundle\Routing;

use Symfony\Component\Routing\RouteCollection;
use Symplify\ModularRouting\Routing\AbstractRouteCollectionProvider;

final class SomeRouteCollectionProvider extends AbstractRouteCollectionProvider
{
    public function getRouteCollection(): RouteCollection
    {
        # routes.yml is the file, where all your routes are located
        return $this->loadRouteCollectionFromFile(__DIR__ . '/routes.yml');
    }
}

4. Register it as a service to your module

# src/SomeBundle/Resources/config/services.yml
services:
    SomeBundle\Routing\SomeRouteCollectionProvider: ~

And that's it! Now all routes are loaded along with your bundle registration.

For further use, just check Readme for Symplify/ModularRouting.



What have you learned today?

If you have some questions or tips for how to make loading of routes simpler, just let me know below.

Happy coding!


Have you find this post useful? Do you want more?

Follow me on Twitter, RSS or support me on GitHub Sponsors.