47

I have a controller which implements all routes/URL(s). I had the idea to offer a generic index over all help-pages.

Is there a way to get all routes defined by a controller (from within a controller) in Symfony2?

fmw42
  • 28,780
  • 5
  • 37
  • 49
Sammy
  • 1,026
  • 1
  • 13
  • 26

6 Answers6

127

What you can do is use the cmd with (up to SF2.6)

php app/console router:debug

With SF 2.7 the command is

php app/console debug:router

With SF 3.0 the command is

php bin/console debug:router

which shows you all routes.

If you define a prefix per controller (which I recommend) you could for example use

php app/console router:debug | grep "<prefixhere>"

to display all matching routes

To display get all your routes in the controller, with basically the same output I'd use the following within a controller (it is the same approach used in the router:debug command in the symfony component)

/**
 * @Route("/routes", name="routes")
 * @Method("GET")
 * @Template("routes.html.twig")
 *
 * @return array
 */
public function routeAction()
{
    /** @var Router $router */
    $router = $this->get('router');
    $routes = $router->getRouteCollection();

    foreach ($routes as $route) {
        $this->convertController($route);
    }

    return [
        'routes' => $routes
    ];
}


private function convertController(\Symfony\Component\Routing\Route $route)
{
    $nameParser = $this->get('controller_name_converter');
    if ($route->hasDefault('_controller')) {
        try {
            $route->setDefault('_controller', $nameParser->build($route->getDefault('_controller')));
        } catch (\InvalidArgumentException $e) {
        }
    }
}

routes.html.twig

<table>
{% for route in routes %}
    <tr>
        <td>{{ route.path }}</td>
        <td>{{ route.methods|length > 0 ? route.methods|join(', ') : 'ANY' }}</td>
        <td>{{ route.defaults._controller }}</td>
    </tr>
{% endfor %}
</table>

Output will be:

/_wdt/{token} ANY web_profiler.controller.profiler:toolbarAction etc.

DerStoffel
  • 2,303
  • 2
  • 13
  • 23
  • Sorry! I would like to access this information from within a controller, so that it can generate an index. – Sammy Apr 11 '13 at 09:40
  • I doubt, that the routing component does care about the controller. – DerStoffel Apr 11 '13 at 09:53
  • And that means? Is there a chance to get that information or not? – Sammy Apr 11 '13 at 11:03
  • I strongly advice to read about routing and dependency injection in symfony, where your tools would be: http://symfony.com/doc/master/book/routing.html http://symfony.com/doc/current/components/dependency_injection/introduction.html – DerStoffel Apr 12 '13 at 07:44
  • I read that, but I was just looking for a way to get the configured routes of a controller from within a controller (php). Qoop's answer helped. Thx – Sammy Apr 12 '13 at 11:14
  • Even if it doesn't answer this question, it is useful. So, +1 :) – Paolo Stefan Aug 05 '13 at 09:54
  • Sorry to repeat comment, but your method too seems to NOT display routes which have no name defined, eg. @Route("/news"). When I tried your method as there were no name="news_route" parameter, I could not get this route mentioned also by `router:debug`.. Any ideas? – Dimitry K May 21 '14 at 10:25
  • Afaik a route needs to have a name. If it does not have one it will not be present. If you define that name manually or not is up to you though. – DerStoffel Jun 03 '15 at 08:14
  • very usefull snippet – L.S Apr 30 '16 at 16:58
  • `php bin/console debug:router` work with version 4 as well – Metafaniel Oct 04 '20 at 00:03
26

You could get all of the routes, then create an array from that and then pass the routes for that controller to your twig.

It's not a pretty way but it works.. for 2.1 anyways..

    /** @var $router \Symfony\Component\Routing\Router */
    $router = $this->container->get('router');
    /** @var $collection \Symfony\Component\Routing\RouteCollection */
    $collection = $router->getRouteCollection();
    $allRoutes = $collection->all();

    $routes = array();

    /** @var $params \Symfony\Component\Routing\Route */
    foreach ($allRoutes as $route => $params)
    {
        $defaults = $params->getDefaults();

        if (isset($defaults['_controller']))
        {
            $controllerAction = explode(':', $defaults['_controller']);
            $controller = $controllerAction[0];

            if (!isset($routes[$controller])) {
                $routes[$controller] = array();
            }

            $routes[$controller][]= $route;
        }
    }

    $thisRoutes = isset($routes[get_class($this)]) ?
                                $routes[get_class($this)] : null ;
qooplmao
  • 16,754
  • 2
  • 38
  • 63
  • That's what I missed: $router = $this->container->get('router'); $collection = $router->getRouteCollection(); $allRoutes = $collection->all(); THX – Sammy Apr 12 '13 at 06:26
  • But this would NOT display routes which have no name defined, eg. `@Route("/news")`. When I tried your method as there were no `name="news_route"` parameter, I could not get this route mentioned. Anyone had similar problem? – Dimitry K May 21 '14 at 10:23
  • As far as I know if you use annotations and don't declare a name then the name is auto generated from the bundle name, the controller name and the action name, (the use of `name=news_route` just overrides this default action). So for `Bills\BlogBundle`, `NewsController`, `indexAction` the name would be auto-generated as `bills_blog_news_index`. – qooplmao May 21 '14 at 15:27
20

I was looking to do just that and after searching the code, I came up with this solution which works for a single controller (or any ressource actually). Works on Symfony 2.4 (I did not test with previous versions) :

$routeCollection = $this->get('routing.loader')->load('\Path\To\Controller\Class');

foreach ($routeCollection->all() as $routeName => $route) {
   //do stuff with Route (Symfony\Component\Routing\Route)
}
yancg
  • 301
  • 2
  • 5
5

If anyone is stumbling on this issue, this is how I exported the routes in the global twig scope (symfony 4).

src/Helper/Route.php

<?php

namespace App\Helper;

use Symfony\Component\Routing\RouterInterface;

class Routes
{
    private $routes = [];

    public function __construct(RouterInterface $router)
    {
        foreach ($router->getRouteCollection()->all() as $route_name => $route) {
            $this->routes[$route_name] = $route->getPath();
        }
    }

    public function getRoutes(): array
    {
        return $this->routes;
    }
}

src/config/packages/twig.yaml

twig:
    globals:
        route_paths: '@App\Helper\Routes'

 

Then in your twig file to populate a javascript variable to use in your scripts

<script>
    var Routes = {
        {% for route_name, route_path in routes_service.routes %}
            {{ route_name }}: '{{ route_path }}',
        {% endfor %}
    }
</script>
Community
  • 1
  • 1
C Alex
  • 97
  • 1
  • 6
3

In Symfony 4 i wanted to get all the routes including controller and actions in one list. In rails you can get this by default.

In Symfony you need to add the parameter show-controllers to the debug:router command.

If somebody looking for the same feature it can be get with:

bin/console debug:router --show-controllers

this will produce a list like the following

------------------------------------------------------------------------- -------------------------------------
Name                   Method    Scheme    Host     Path                    Controller
------------------------------------------------------------------------- -------------------------------------
app_some_good_name     ANY       ANY       ANY      /example/example        ExampleBundle:Example:getExample
------------------------------------------------------------------------- -------------------------------------
rob
  • 1,839
  • 7
  • 22
  • 32
0

The safest way to proceed is to use the symfony controller resolver, because you never know if your controller is defined as a fully qualified class name, a service, or whatever callable declaration.

    foreach ($this->get('router')->getRouteCollection() as $route) {
        $request = new Request();
        $request->attributes->add($route->getDefaults());

        [$service, $method] = $this->resolver->getController($request);

        // Do whatever you like with the instanciated controller
    }
Alain Tiemblo
  • 32,952
  • 14
  • 114
  • 147