Symfony 2: How to get route defaults by route name

2019-05-26 19:04发布

问题:

Is it possible to retrieve info about a certain route by its name, or get a list of all routes?

I need to be able to fetch the _controller value in defaults for any route, not only the current.

Is this possible and how?

P.S.: I found I could get the path to the routes YAML being used, but reparsing it seems unnecessary and heavy.

回答1:

I am really good at answering my own questions..

To get routes use getRouteCollection() on the router ($this -> get('router') -> getRouteCollection() inside a controller), then you get RouteCollection instance on which you can all() or get($name).



回答2:

As described in my comment above Router::getRouteCollection is really slow and not intended for use in production code.

So if you really need it fast, you have to hack your way through it. Be warned, this is going to be hackish:


Directly accessing the dumped route data

To speed up route matching, Symfony compiles all static routes into one big PHP class file. This file is generated by Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper and declares a Symfony\Component\Routing\Generator\UrlGenerator that stores all route definitions in a private static called $declaredRoutes.

$declaredRoutes is an array of compiled route fields indexed by the route's name. Among others (see below) these fields also contain the route defaults.

In order to access $declaredRoutes we have to use a \ReflectionProperty.

So the actual code is:

// If you don't use a custom Router (e.g., a chained router) you normally
// get the Symfony router from the container using:
// $symfonyRouter = $container->get('router');
// After that, you need to get the UrlGenerator from it.
$generator = $symfonyRouter->getGenerator();

// Now read the dumped routes.
$reflectionProperty = new \ReflectionProperty($generator, 'declaredRoutes');
$reflectionProperty->setAccessible(true);
$dumpedRoutes = $reflectionProperty->getValue($generator);

// The defaults are at index #1 of the route array (see below).
$routeDefaults = $dumpedRoutes['my_route'][1];

Fields of the route array

The fields of each route are filled by the above mentioned Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper like this:

// [...]
$compiledRoute = $route->compile();

$properties = array();
$properties[] = $compiledRoute->getVariables();
$properties[] = $route->getDefaults();
$properties[] = $route->getRequirements();
$properties[] = $compiledRoute->getTokens();
$properties[] = $compiledRoute->getHostTokens();
$properties[] = $route->getSchemes();
// [...]

So to access its requirements you would use:

$routeRequirements = $dumpedRoutes['my_route'][2];

Bottom line

I've looked through the Symfony manual, the source code, forums, stackoverflow etc. but still wasn't able to find a better way of doing this.

It's brutal, ignores the API, and might break in future updates (although it hasn't changed in the most recent Symfony 4.1: PhpGeneratorDumper on GitHub).

But it's rather short and fast enough to be used in production.