如何在Symfony2中获取控制器的所有路由列表?

59

我有一个控制器,它实现了所有路由/URL

我想提供一个通用的索引来展示所有帮助页面。

Symfony2中,有没有一种方法可以在控制器内获取由控制器定义的所有路由?

7个回答

144
你可以使用 (最多到 SF2.6) 的 cmd。
php app/console router:debug

使用 SF 2.7 版本的命令为:

php app/console debug:router

使用SF 3.0时,命令为:

php bin/console debug:router

这将向您展示所有路由。

如果您为每个控制器定义一个前缀(我建议这样做),那么您可以使用以下示例:

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

显示所有匹配的路由

要在控制器中获取所有路由,并生成基本相同的输出, 我会使用以下代码(这是Symfony组件中router:debug命令使用的相同方法):

/**
 * @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) {
        }
    }
}

路由.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>

输出结果将为:

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


抱歉!我想从控制器内访问此信息,以便生成索引。 - Sammy
即使它未回答此问题,也是有用的。因此,+1 :) - Paolo Stefan
抱歉重复评论,但是您的方法似乎也不能显示没有定义名称的路由,例如@Route("/news")。当我尝试使用您的方法时,因为没有name="news_route"参数,我无法在router:debug中找到此路由的提及...有什么想法吗? - Dimitry K
据我所知,路由需要有一个名称。如果没有名称,它将不会存在。但是,你可以选择手动定义该名称或者不定义。 - DerStoffel
非常有用的代码片段。 - L.S
显示剩余5条评论

29

你可以获取所有路由,然后从中创建一个数组,再将该控制器的路由传递给你的twig。

这不是一种优美的方式,但它在2.1版本中有效。

    /** @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 ;

这就是我错过的: $router = $this->container->get('router'); $collection = $router->getRouteCollection(); $allRoutes = $collection->all(); - Sammy
但是这样不会显示没有定义名称的路由,例如 @Route("/news")。当我尝试使用您的方法时,因为没有 name="news_route" 参数,我无法获取到此路由。有人遇到过类似的问题吗? - Dimitry K
据我所知,如果您使用注释并且没有声明名称,则名称将从包名称、控制器名称和操作名称自动生成(使用name = news_route只是覆盖此默认操作)。 因此,对于Bills \ BlogBundleNewsControllerindexAction,名称将自动生成为bills_blog_news_index - qooplmao

20

我正想做到这一点,在搜索代码后,我想出了这个解决方案,适用于单个控制器(或任何资源)。 适用于Symfony 2.4(我没有在以前的版本中测试):

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

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

获取控制器所有操作(路由)的有趣方法。 - L.S
迄今为止最佳答案 - Isky

7

如果有人遇到这个问题,这是我在全局Twig范围内(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'

然后在你的Twig文件中,填充一个JavaScript变量以在你的脚本中使用

<script>
    var Routes = {
        {% for route_name, route_path in routes_service.routes %}
            {{ route_name }}: '{{ route_path }}',
        {% endfor %}
    }
</script>

4

在Symfony 4中,我想要得到包含控制器和操作的所有路由列表。在Rails中,默认情况下可以获取到这个列表。

在Symfony中,您需要将参数show-controllers添加到debug:router命令中。

如果有人正在寻找相同的功能,可以使用以下方式获得:

bin/console debug:router --show-controllers

这将会生成以下类似的列表:
------------------------------------------------------------------------- -------------------------------------
Name                   Method    Scheme    Host     Path                    Controller
------------------------------------------------------------------------- -------------------------------------
app_some_good_name     ANY       ANY       ANY      /example/example        ExampleBundle:Example:getExample
------------------------------------------------------------------------- -------------------------------------

2

最安全的方法是使用Symfony控制器解析器,因为您永远不知道您的控制器是否定义为完全限定的类名、服务或任何可调用声明。

    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
    }

1

因为您需要从控制器中获取路由信息,所以可以利用Symfony的自动装配。如果配置正确,您只需将RouterInterface传递给控制器中的任何路由即可。

#[Route('/', name: 'app_default')]
public function someRoute(RouterInterface $router): JsonResponse
{
    $routesPaths = [];

    foreach ($router->getRouteCollection()->all() as $routeName => $route) {
        $routesPaths["$routeName"] = $route->getPath();
    }

    return new JsonResponse([
        'availableRoutes' => $routesPaths,
    ]);
}

然而,如果您需要在多个控制器中使用此逻辑,则应该将逻辑封装在一个单独的类中,就像@C Alex在他的答案中所做的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接