Как узнать текущий маршрут в Symfony 2?

224

Как мне узнать текущий маршрут в Symfony 2?

Например, routing.yml:

somePage:
   pattern: /page/
   defaults: { _controller: "AcmeBundle:Test:index" }

Как я могу получить это somePageзначение?

IlyaDoroshin
источник

Ответы:

323

Из чего-то, что является ContainerAware (например, контроллер):

$request = $this->container->get('request');
$routeName = $request->get('_route');
tuxedo25
источник
2
@ Получите переломный момент для вас, проверьте meta.stackexchange.com/questions/155258/…
NullPoiиteя
37
github.com/symfony/symfony/issues/854 request.attributes.get ('_ route') ненадежен, поскольку он предназначен только для целей отладки (сказал Symfony dev) и не работает, если запрос переадресован ... см. ответ суперновы которые задокументированы и более
надежны
3
Причина, по которой это не работает при пересылке чего-либо, связана с тем, что вы пересылаете данные непосредственно на контроллер, а не на маршрут. Таким образом, Symfony не знает, для чего он нужен. Как правило, у вас есть один маршрут к одному контроллеру, поэтому может показаться странным, что он не может сообщить о чем-либо, кроме «_internal», однако возможно создать контроллеры общего назначения, которые будут связаны с более чем одним определением маршрута. Когда вы рассматриваете все это, я думаю, что эта «ошибка» имеет больше смысла.
jzimmerman2011
@ tuxedo25 Подумайте об использовании RequestStack: symfony.com/blog/new-in-symfony-2-4-the-request-stack
mYkon
2
$ request-> Get ( '_ маршрут'); медленный ! $ request-> attributes-> Get ( '_ маршрут'); лучше, если вам не нужна гибкость
Том Том
190

С веточкой: {{ app.request.attributes.get('_route') }}

Матье
источник
8
Спасибо! Использую <body class="{{ app.request.get('_route') | replace({'_' : '-'}) }}">для подачи странички css :)
Салман фон Аббас
10
github.com/symfony/symfony/issues/854 request.attributes.get ('_ route') ненадежен, поскольку он предназначен только для целей отладки (сказал Symfony dev) и не работает, если запрос переадресован ... см. ответ суперновы которые задокументированы и более
надежны
48

Я думаю, что это самый простой способ сделать это:

class MyController extends Controller
{
    public function myAction($_route)
    {
        var_dump($_route);
    }

    .....
сверхновая звезда
источник
3
Можете ли вы добавить больше объяснений или показать пример выходных данных, чтобы уточнить, как это решает проблему?
Чарли
1
@Charlie Это предопределенная переменная, которая дает вам совпадающее имя маршрута
сверхновая
2
Это, безусловно, лучший ответ на оригинальный вопрос. В качестве примечания: однако, он не работает с такими подзапросами, как {% render "SomeBundle:SomeController:someAction" %}, где вы снова получите значение _internal.
netmikey
2
Жаль, что это работает только в оригинальном действии, для любой другой функции, которую оно должно быть передано.
Дарек Вендрыховски
27

Symfony 2.0-2.1
Используйте это:

    $router = $this->get("router");
    $route = $router->match($this->getRequest()->getPathInfo());
    var_dump($route['_route']);

Это не даст вам _internal.

Обновление для Symfony 2.2+: это не работает, начиная с Symfony 2.2+. Я открыл ошибку, и ответ был "по замыслу". Если вы хотите получить маршрут в дополнительном действии, вы должны передать его в качестве аргумента

{{ render(controller('YourBundle:Menu:menu', { '_locale': app.request.locale, 'route': app.request.attributes.get('_route') } )) }}

И ваш контроллер:

public function menuAction($route) { ... }
jsgoupil
источник
github.com/symfony/symfony/issues/854 Я не уверен в этом, $route['_route']кажется проблематичным, но, возможно, это не Symfony, о котором говорит dev. Поваренная книга не упоминает о _routeо $router->match()выходе ..
luiges90
Я полностью согласен с @ luiges90. В PHPDoc $router->match()говорится: «массив @return - массив параметров», который кажется очень внутренним. Я не хочу на это полагаться, но сейчас, похоже, это единственное жизнеспособное решение при работе с подзапросами.
netmikey
19

Не существует решения, которое работает для всех случаев использования. Если вы используете метод $ request-> get ('_ route') или его варианты, он вернет _internal для случаев, когда переадресация имела место.

Если вам нужно решение, которое работает даже с переадресацией, вы должны использовать новую службу RequestStack, которая появилась в 2.4, но это нарушит поддержку ESI :

$requestStack = $container->get('request_stack');
$masterRequest = $requestStack->getMasterRequest(); // this is the call that breaks ESI
if ($masterRequest) {
    echo $masterRequest->attributes->get('_route');
}

Из этого вы можете сделать расширение ветки, если вам это нужно в шаблонах.

К. Норберт
источник
Итак ... как ваше решение не работает точно для всех вариантов использования?
greg0ire
11

_routeэто не путь и никогда не было . По словам Фабьена, который всегда создавал Symfony, он всегда предназначался для отладки . Это ненадежно, так как не будет работать с такими вещами, как переадресация и другие прямые вызовы контроллеров, такие как частичный рендеринг.

Вам нужно ввести название вашего маршрута в качестве параметра в вашем контроллере, смотрите документацию здесь

Кроме того, пожалуйста, никогда не используйте, $request->get('');если вам не нужна гибкость, это намного медленнее, чем использование get для конкретного пакета свойств, который вам нужен (атрибуты, запрос или запрос), поэтому $request->attributes->get('_route');в этом случае.

Том Том
источник
4
Хорошо, вы в основном предлагаете добавить дополнительную информацию к каждому маршруту в этих файлах вместо того, чтобы получить название маршрута? …
Хараф
1
Да, особенно если вам нужно иметь возможность вызывать сам контроллер позже по линии (переадресация, частичный рендеринг и т. Д.), Передавая имя в качестве параметра, это единственный способ, потому что вы вообще не вызываете маршрут в этом кейс. Что касается _route, предназначенного для целей отладки, не берите это на себя ^^ '
Том Том
7
$request->attributes->get('_route');

Вы можете получить имя маршрута из объекта запроса из контроллера.

Венкат Котра
источник
4

Все, что я получаю от этого _internal

Я получаю имя маршрута изнутри контроллера с помощью $this->getRequest()->get('_route'). даже кода, предлагаемого Tuxedo25 возвращает_internal

Этот код выполняется в так называемом «Компоненте» в Symfony 1.X; Не контроллер страницы, а часть страницы, которая нуждается в некоторой логике.

Эквивалентный код в Symfony 1.X: sfContext::getInstance()->getRouting()->getCurrentRouteName();

alexismorin
источник
2
Решил это сам. В представлении:$view['request']->getParameter('_route');
alexismorin
5
это потому, что вы используете {% render... %}звонки с standalone=true. При включенном кэшировании (AppCache.php или varnish with ESI) это приведет к тому, что автономные представления будут запрашиваться с отдельным HTTP-запросом (именно здесь начинается маршрут _internal), чтобы ro мог быть независимо кэширован.
Мартин Шухфус
2

В Symfony 3.3 я использовал этот метод и работал нормально.

У меня есть 4 маршрута, как

admin_category_index, admin_category_detail, admin_category_create, admin_category_update

И только одна строка делает активный класс для всех маршрутов.

<li  {% if app.request.get('_route') starts with 'admin_category' %} class="active"{% endif %}>
 <a href="{{ path('admin_category_index') }}">Product Categoires</a>
</li>
Мухаммед Шахзад
источник
1

Чтобы получить текущий маршрут на основе URL (более надежный в случае пересылки):

public function getCurrentRoute(Request $request)
{
    $pathInfo    = $request->getPathInfo();
    $routeParams = $this->router->match($pathInfo);
    $routeName   = $routeParams['_route'];
    if (substr($routeName, 0, 1) === '_') {
        return;
    }
    unset($routeParams['_route']);

    $data = [
        'name'   => $routeName,
        'params' => $routeParams,
    ];

    return $data;
}
Ален Тьембло
источник
0

В Symfony 4.2.7 я могу реализовать следующее в своем шаблоне ветки, который отображает имя пользовательского маршрута, которое я определил в своих контроллерах.

В index.html.twig

<div class="col">
    {% set current_path =  app.request.get('_route') %}
    {{ current_path }}
</div>

В моем контроллере


    ...

    class ArticleController extends AbstractController {
        /**
         * @Route("/", name="article_list")
         * @Method({"GET"})
         */
        public function index() {
        ...
        }

        ...
     }

Результат выводит «article_list» на нужную страницу в моем браузере.

klewis
источник
0

Для тех, кому нужен текущий маршрут для Symfony 3, это то, что я использую

<?php
   $request = $this->container->get('router.request_context');
   //Assuming you are on user registration page like https://www.yoursite.com/user/registration
   $scheme = $request->getScheme(); //This will return https
   $host = $request->getHost(); // This will return www.yoursite.com
   $route = $request->getPathInfo(); // This will return user/registration(don't forget this is registrationAction in userController
   $name = $request->get('_route'); // This will return the name.
?>
Адереми Дайо
источник
3
Это не вернет название обработанного маршрута
Nico Haase
@NicoHaase Это не ракетостроение, у вас уже есть объект запроса
Aderemi Dayo
-2

если вы хотите получить имя маршрута в вашем контроллере, то вам нужно внедрить запрос (вместо того, чтобы получать из контейнера из-за UPGRADE Symfony и затем вызывать get ('_ route').

public function indexAction(Request $request)
{
    $routeName = $request->get('_route');
}

если вы хотите получить название маршрута в ветке, чем вы должны получить его как

{{ app.request.attributes.get('_route') }}
Вазген Манукян
источник
1
Не рекомендуется использовать $request->get()напрямую, потому что это медленно: github.com/symfony/http-foundation/blob/2.8/Request.php#L712
ricko zoe