Search code examples
phpsymfonysilexsymfony4

Grouped routes in multiple controllers in Symfony 4


I'm rewriting my Silex-based application to Symfony 4, as the Silex will be deprecated in a while from now. Everything works great so far, but I have a problem with nested routes.

I had lots of nested (child routes) in Silex application with different controllers assigned to them.

$app->match('/api', function (ControllerCollection $api) {
    $api->get('/homepage', 'ControllerOne::index');
    $api->get('/contact', 'ControllerTwo::index');
});

This was pretty easy in Silex, but now in Symfony 4, I'm using annotations for the routes' management and it seems like I can't find a way to group those routes.

It's annoying especially when it comes to routes with _locale as the syntax for those routes is pretty long and still.. it's not a good way to have it everywhere in case I need to change the _locale prefix some day to something like /home/{_locale}/.

ControllerOne extends Controller 
{
    /**
     * @Route("/{_locale}/",
     *     name="root",
     *     methods="GET",
     *     requirements={"_locale": "en|fr"}
     * )
     *
     * @return Response
     */
    public function index(): Response
    {
        return $this->render('some.html.twig');
    }
}

ControllerTwo extends Controller
{
    /**
     * @Route("/{_locale}/homepage",
     *     name="homepage",
     *     methods="GET",
     *     requirements={"_locale": "en|fr"}
     * )
     *
     * @return Response
     */
    public function index(): Response
    {
        return $this->render('some2.html.twig');
    }
}

UPDATE

I had an idea to create some sort of PrefixedController where I'd specify the prefix over the class and the extend that PrefixedController instead of the basic Controller, but it seems to don't work.

/**
 * @Route("/{_locale}", requirements={"_locale": "en|fr"})
 */
controller PrefixedController extends Controller 
{
}

controller ControllerOne extends PrefixedController
{
    /**
     * @Route("/", methods="GET")
     * @Return Response
     */
    public function index(): Response 
    {
        return $this->render('some.html.twig');
    }
}

But when I navigate to /en/ it can't match the route.


Solution

  • This can be done in the main routing file where the routing resources are imported. In Symfony 4 it is in config/routes/annotations.yaml. Then to provide a prefix /{_locale} for the imported routes uses the prefix option:

    # config/routes/annotations.yaml
    controllers:
        resource: '../src/Controller/'
        type: annotation
        prefix: /{_locale}
    

    The path of each route being loaded from the new routing resource will now be prefixed with the placeholder /{_locale}.