Symfony 2: générer une url dynamique dans twig dans du code javascript
J’ai eu à faire face à un problème que vous allez très certainement rencontrer si vous faites Symfony2. Dans les fichiers de template, vous allez sûrement mettre du Javascript. Exemple :
<script type="text/javascript"> <!-- function verif_formulaire(){ window.location = '/test/mon/url/'; } --> </script>
Maintenant, si on essaie de faire ça en Twig, c’est simple. Je ne m’attarderai que sur l’URL :
window.location = '{{ path('my_path') }}';
Supposons que votre path nécessite un paramètre, par exemple, dans mon cas, le code postal :
window.location = '{{ path('my_path', {'cp': "13480" }) }}';
Facile. Mais supposons que votre code en JavaScript veuille le générer dynamiquement :
/* récupération de la valeur quelque part : */ var monCP = document.getElementById('cp').value; window.location = ="{{ path('hqf_pizzas_searchpage', {'cp': monCP }) }}";
Eh bien ça ne fonctionnera pas sur Symfony2. Ne cherchez pas c’est comme ça. Vous aurez une erreur. L’erreur, pour reprendre mon code, était :
Variable "monCP" does not exist in HQFPizzasBundle:Default:index.html.twig at line 11
Voici la solution que j’ai trouvée : je reprends ma configuration et il vous suffira de l’adapter à vos besoins. Dans mon fichier de routing src/HQF/Bundle/PizzasBundle/Resources/config/routing.yml
, j’ai ce path qui nécessite le paramètre cp
:
hqf_pizzas_searchpage: pattern: /search/cp/{cp} defaults: { _controller: ... }
L’objectif est de ressortir le path avec un '%s'
dedans, de manière à pouvoir avoir une URL qui ressemble à :
/search/cp/%s
Ainsi, il suffira juste après d’utiliser la fonction Twig ‘format
‘ et d’y passer la variable JavaScript, par exemple monCP
.
Ainsi cet ordre twig:
{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) | format('monCP') }}
génèrera ceci :
/search/cp/monCP
L’objectif final est de sortir du vrai code JavaScript qui ressemble à :
window.location="/search/cp/"+monCP+"";
Donc si veut y arriver, le mélange code Twig + JavaScript, avec les guillemets, devrait être :
window.location = "{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) | format('"+monCP+"') }}"
Seulement, problème : il escape tout ! Le code généré sera ainsi :
window.location ="/pizzas/search/cp/%25s";
Solution : pour que twig n’échappe pas le texte, il faut créer son propre filtre Twig !
Voici les étapes à suivre :
J’ai crée mon fichier src/HQF/Bundle/PizzasBundle/Twig/UrlDecodeExtension.php
dans lequel j’ai mis ce code :
<?php namespace HQF\Bundle\PizzasBundle\Twig; class UrlDecodeExtension extends \Twig_Extension { public function getFilters() { return array( 'url_decode' => new \Twig_Filter_Method($this, 'urlDecode'), ); } public function urlDecode( $url ) { return urldecode( $url ); } public function getName() { return 'url_decode_extension'; } }
Ensuite, je l’ai enregistré dans les services.
C’est dans le fichier src/HQF/Bundle/PizzasBundle/Resources/config/services.yml
les lignes :
services: cme.twig.url_decode_extension: class: HQF\Bundle\PizzasBundle\Twig\UrlDecodeExtension tags: - { name: twig.extension }
A partir de là le filtre url_decode
fonctionne. Il suffit de faire le code qui suit :
/* récupération de la valeur quelque part */ var monCP = document.getElementById('cp').value; window.location ="{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) | url_decode | format('"+monCP+"') | raw }}";
Afin de générer cela en JavaScript :
/* récupération de la valeur quelque part */ var monCP = document.getElementById('cp').value; window.location ="/pizzas/search/cp/"+monCP+"";
Ce qui est du code JavaScript parfaitement exécutable.
Voici les explications pas à pas :
window.location ="{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) }}";
Génère cela :
window.location ="/pizzas/search/cp/%25s";
C’est échappé, et il ne le faut pas ! Donc ajouter le filtre url_decode
:
window.location ="{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) | url_decode }}";
Là le résultat sera celui attendu :
window.location ="/pizzas/search/cp/%s";
Ensuite on y ajoute la fonction format
afin d’y ajouter la variable JavaScript :
window.location ="{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) | url_decode | format('"+monCP+"') }}";
Mais là encore le résultat sera échappé :
window.location ="/pizzas/search/cp/"+monCP+"";
Donc il faut lui dire de ressortir le résultat final au format raw
:
window.location ="{{ path('hqf_pizzas_searchpage', {'cp': "%s" }) | url_decode | format('"+monCP+"') | raw }}";
Et le résultat de sortie sera (enfin !) parfait :
window.location ="/pizzas/search/cp/"+monCP+"";
Cet article est un mélange de l’explication de création des filtres Twig, ici, et de la question qui ressemble très fortement à la mienne sur stackoverflow, ici.
En espérant que cela serve à quelqu’un, un jour 😉
6 comments