symfony / symfony-docs

The Symfony documentation
https://symfony.com/doc
Other
2.15k stars 5.1k forks source link

Route priority #20061

Closed justin-oh closed 1 month ago

justin-oh commented 1 month ago

I'm unsure if route priority is not working or is not described properly.

In the current 6.4 documentation:

Symfony evaluates routes in the order they are defined. If the path of a route matches many different patterns, it might prevent other routes from being matched. In YAML and XML you can move the route definitions up or down in the configuration file to control their priority. In routes defined as PHP attributes this is much harder to do, so you can set the optional priority parameter in those routes to control their priority:

The priority parameter expects an integer value. Routes with higher priority are sorted before routes with lower priority. The default value when it is not defined is 0.

It sounds like we should be able to do this:

namespace MyBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;

class FirstController extends AbstractController
{
    #[Route('/profile', name: 'profile', methods: ['GET', 'POST'])]
    public function profile(): Response
    {
        // ...
    }
}

and override it in another controller:

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;

class SecondController extends AbstractController
{
    #[Route('/profile', name: 'profile', methods: ['GET', 'POST'], priority: 9999)]
    public function profile(): Response
    {
        // ...
    }
}

I picture the code loading all routes into a single array in the order they are defined, then sorting them based on priority such that higher priority routes are at the top and lower at the bottom. Then when a path is matched, the code would loop through this sorted array of routes and stop at the first match.

However, this seems to not be the case. The only way I can get SecondController to override FirstController is by changing the order they are loaded.

javiereguiluz commented 1 month ago

I've tried to reproduce this error in one of my Symfony apps and I couldn't:

(1) I changed the path of an existing action to match the same path of a different action (2) I browsed the URL of that path ... and the changed action showed up (3) I set priority: 9999 to the route of the original action ... reloaded the page ... and now the original action showed up

Both routes were defined in different files (in controller attributes), so this priority option works as expected and it's not only for routes defined in the same file.

So, I'm going to close this as "not planned" ... but, if you can reproduce this bug in your own app, please create a reproducer (see e.g. https://symfonycasts.com/blog/symfony-reproducer) and share it in an issue of the Symfony code repository (https://github.com/symfony/symfony) so we can fix it.

Thanks!