Comment obtenir l'itinéraire actuel dans Symfony 2?


224

Comment obtenir l'itinéraire actuel dans Symfony 2?

Par exemple routing.yml:

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

Comment puis-je obtenir cette somePagevaleur?

Réponses:


323

À partir de quelque chose qui est ContainerAware (comme un contrôleur):

$request = $this->container->get('request');
$routeName = $request->get('_route');

2
@got a switchwation for you check meta.stackexchange.com/questions/155258/…
NullPoiиteя

37
github.com/symfony/symfony/issues/854 request.attributes.get ('_ route') n'est pas fiable car il n'est utilisé qu'à des fins de débogage (symfony dev dit) et ne fonctionne pas si la demande est transmise ... voir la réponse de supernova qui sont documentés et sont plus sûrs
luiges90

3
La raison pour laquelle cela ne fonctionne pas lorsque quelque chose est transféré est due au fait que vous transférez directement vers un contrôleur, pas une route. En tant que tel, Symfony ne sait pas pour quelle route il s'agit. En règle générale, vous avez une route vers un contrôleur, il peut donc sembler étrange que cela ne puisse pas signaler autre chose que "_internal", cependant, il est possible de créer des contrôleurs à usage général qui sont associés à plusieurs définitions de route. Quand vous considérez tout cela, je pense que ce "gotcha" est plus logique.
jzimmerman2011

@ tuxedo25 Pensez à utiliser RequestStack: symfony.com/blog/new-in-symfony-2-4-the-request-stack
mYkon

2
$ request-> get ('_ route'); est lent ! $ request-> attributes-> get ('_ route'); c'est mieux si vous n'avez pas besoin de flexibilité
Tom Tom

190

Avec Twig: {{ app.request.attributes.get('_route') }}


8
Je vous remercie! J'utilise <body class="{{ app.request.get('_route') | replace({'_' : '-'}) }}">pour appliquer un CSS spécifique à une page :)
Salman von Abbas

10
github.com/symfony/symfony/issues/854 request.attributes.get ('_ route') n'est pas fiable car il n'est utilisé qu'à des fins de débogage (symfony dev dit) et ne fonctionne pas si la demande est transmise ... voir la réponse de supernova qui sont documentés et sont plus sûrs
luiges90

48

Je pense que c'est la façon la plus simple de le faire:

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

    .....

3
Pouvez-vous ajouter plus d'explications ou montrer un exemple de sortie pour clarifier comment cela résout le problème?
Charlie


1
@Charlie C'est une variable prédéfinie qui vous donne l'itinéraire "nom" correspondant
supernova

2
C'est certainement la meilleure réponse à la question d'origine. En remarque: cela ne fonctionne pas, cependant, avec des sous-requêtes comme {% render "SomeBundle:SomeController:someAction" %}, où vous obtiendrez à nouveau la valeur '_internal'.
netmikey

2
Dommage que cela ne fonctionne que dans l'action d'origine, pour toute autre fonction, il doit être transmis.
Darek Wędrychowski

27

Symfony 2.0-2.1
Utilisez ceci:

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

Celui-là ne vous donnera pas _internal.

Mise à jour pour Symfony 2.2+: cela ne fonctionne pas au démarrage de Symfony 2.2+. J'ai ouvert un bug et la réponse était "par conception". Si vous souhaitez obtenir l'itinéraire dans une sous-action, vous devez le passer en argument

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

Et votre contrôleur:

public function menuAction($route) { ... }

github.com/symfony/symfony/issues/854 Je ne suis pas sûr de cela, cela $route['_route']semble problématique, mais ce n'est peut-être pas le sujet de dev de symfony. Le livre de cuisine ne mentionne pas _routede $router->match()sortie ..
luiges90

Je suis entièrement d'accord avec @ luiges90. Le PHPDoc de $router->match()dit "@return array Un tableau de paramètres" qui semble très interne. Je ne veux pas m'y fier, mais pour le moment, cela semble être la seule solution viable pour traiter les sous-demandes.
netmikey

19

Il n'y a pas de solution qui fonctionne pour tous les cas d'utilisation. Si vous utilisez la méthode $ request-> get ('_ route') ou ses variantes, elle renverra '_internal' pour les cas où le transfert a eu lieu.

Si vous avez besoin d'une solution qui fonctionne même avec le transfert, vous devez utiliser le nouveau service RequestStack, arrivé en 2.4, mais cela interrompra la prise en charge ESI :

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

Vous pouvez en faire une extension de brindille si vous en avez besoin dans les modèles.


Alors… comment votre solution ne fonctionne-t-elle pas exactement pour tous les cas d'utilisation?
greg0ire

11

_routen'est pas la voie à suivre et ne l'a jamais été . Il a toujours été conçu à des fins de débogage selon Fabien qui a créé Symfony. Il n'est pas fiable car il ne fonctionnera pas avec des choses comme le transfert et d'autres appels directs aux contrôleurs comme le rendu partiel.

Vous devez injecter le nom de votre route comme paramètre dans votre contrôleur, voir la doc ici

De plus, veuillez ne jamais utiliser $request->get('');si vous n'avez pas besoin de la flexibilité, c'est beaucoup plus lent que d'utiliser get sur le sac de propriété spécifique dont vous avez besoin (attributs, requête ou demande), donc $request->attributes->get('_route');dans ce cas.


4
Ok, vous suggérez essentiellement d'ajouter des informations supplémentaires à chaque itinéraire dans ces fichiers au lieu d'obtenir le nom de l'itinéraire? …
Charaf le

1
Oui, surtout si vous devez être en mesure d'appeler le contrôleur lui-même plus tard sur la ligne (vers l'avant, rendu partiel, etc ...) en passant le nom en tant que paramètre est le seul moyen ici parce que vous n'appelez pas du tout une route dans ce Cas. Quant à _route étant destiné à des fins de débogage, ne m'en privez pas ^^ '
Tom Tom

7
$request->attributes->get('_route');

Vous pouvez obtenir le nom de l'itinéraire à partir de l'objet de demande à partir du contrôleur.


4

Tout ce que je retiens c'est _internal

$this->getRequest()->get('_route'). J'obtiens le nom de la route depuis l'intérieur d'un contrôleur avec Même le code tuxedo25 suggère des retours_internal

Ce code est exécuté dans ce qui était appelé un «composant» dans Symfony 1.X; Pas le contrôleur d'une page mais une partie d'une page qui a besoin de logique.

Le code équivalent dans Symfony 1.X est: sfContext::getInstance()->getRouting()->getCurrentRouteName();


2
Je l'ai résolu moi-même. Dans une vue:$view['request']->getParameter('_route');
alexismorin

5
c'est parce que vous utilisez des {% render... %}appels avec standalone=true. Lorsque la mise en cache (AppCache.php ou vernis avec ESI) est activée, les vues autonomes seront demandées avec une requête HTTP séparée (c'est là que la route _internalentre en jeu) afin de pouvoir être mises en cache indépendamment.
Martin Schuhfuß

2

Avec Symfony 3.3, j'ai utilisé cette méthode et j'ai bien fonctionné.

J'ai 4 itinéraires comme

admin_category_index, admin_category_detail, admin_category_create, admin_category_update

Et une seule ligne crée une classe active pour tous les itinéraires.

<li  {% if app.request.get('_route') starts with 'admin_category' %} class="active"{% endif %}>
 <a href="{{ path('admin_category_index') }}">Product Categoires</a>
</li>

1

Pour obtenir l'itinéraire actuel en fonction de l'URL (plus fiable en cas de transfert):

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

Avec Symfony 4.2.7, je suis capable d'implémenter ce qui suit dans mon modèle de brindille, qui affiche le nom de route personnalisé que j'ai défini dans mes contrôleurs.

Dans index.html.twig

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

Dans mon contrôleur


    ...

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

        ...
     }

Le résultat imprime "article_list" sur la page souhaitée dans mon navigateur.


0

Pour tous ceux qui ont besoin de l'itinéraire actuel pour Symfony 3, voici ce que j'utilise

<?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
Cela ne retournera pas le nom de l'itinéraire traité
Nico Haase

@NicoHaase Ce n'est pas sorcier, vous avez déjà l'objet de demande
Aderemi Dayo

-2

si vous voulez obtenir le nom de la route dans votre contrôleur, vous devez injecter la demande (au lieu d'obtenir du conteneur en raison de Symfony UPGRADE et d'appeler get ('_ route').

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

si vous voulez obtenir le nom de l'itinéraire en brindille, vous devez l'obtenir comme

{{ app.request.attributes.get('_route') }}

1
Il n'est pas recommandé d'utiliser $request->get()directement car il est lent: github.com/symfony/http-foundation/blob/2.8/Request.php#L712
ricko zoe
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.