Les templates Twig
À savoir
Première chose à savoir sur Twig : vous pouvez afficher des variables et pouvez exécuter des expressions. Ce n'est pas la même chose :
{{ … }}
affiche quelque chose ;{% … %}
fait quelque chose ;{# … #}
n'affiche rien et ne fait rien : c'est la syntaxe pour les commentaires, qui peuvent être sur plusieurs lignes.
Afficher des variables
Syntaxe de base pour afficher des variables
Afficher une variable se fait avec les doubles accolades «
{{ … }}
». Voici quelques exemples.
Description
|
Exemple Twig
|
Équivalent PHP
|
---|---|---|
Afficher une variable
| Pseudo : {{ pseudo }} | Pseudo : <?php echo $pseudo; ?> |
Afficher l'index d'un tableau
| Identifiant : {{ user['id'] }} | Identifiant : <?php echo $user['id']; ?> |
Afficher l'attribut d'un objet, dont le getter respecte la convention
$objet->getAttribut() | Identifiant : {{ user.id }} | Identifiant : <?php echo $user->getId(); ?> |
Afficher une variable en lui appliquant un filtre. Ici, « upper » met tout en majuscules :
| Pseudo en majuscules : {{ pseudo|upper }} | Pseudo en lettre majuscules : <?php echo strtoupper($pseudo); ?> |
Afficher une variable en combinant les filtres.
« striptags » supprime les balises HTML. « title » met la première lettre de chaque mot en majuscule. Notez l'ordre d'application des filtres, ici striptags est appliqué, puis title . | Message : {{ news.texte|striptags|title }} | Message : <?php echo ucwords(strip_tags($news->getTexte())); ?> |
Utiliser un filtre avec des arguments.
Attention, il faut que date soit un objet de type Datetime ici. | Date : {{ date|date('d/m/Y') }} | Date : <?php echo $date->format('d/m/Y'); ?> |
Concaténer
| Identité : {{ nom ~ " " ~ prenom }} | Identité : <?php echo $nom.' '.$prenom; ?> |
Précisions sur la syntaxe {{ objet.attribut }}
Le fonctionnement de la syntaxe
{{ objet.attribut }}
est un peu plus complexe qu'elle n'en a l'air. Elle ne fait pas seulement objet->getAttribut
. En réalité, voici ce qu'elle fait exactement :- Elle vérifie si
objet
est un tableau, et siattribut
est un index valide. Si c'est le cas, elle afficheobjet['attribut']
. - Sinon, et si
objet
est un objet, elle vérifie siattribut
est un attribut valide (public donc). Si c'est le cas, elle afficheobjet->attribut
. - Sinon, et si
objet
est un objet, elle vérifie siattribut()
est une méthode valide (publique donc). Si c'est le cas, elle afficheobjet->attribut()
. - Sinon, et si
objet
est un objet, elle vérifie sigetAttribut()
est une méthode valide. Si c'est le cas, elle afficheobjet->getAttribut()
. - Sinon, et si
objet
est un objet, elle vérifie siisAttribut()
est une méthode valide. Si c'est le cas, elle afficheobjet->isAttribut()
. - Sinon, elle n'affiche rien et retourne
null
.Les filtres utiles
Il y a quelques filtres disponibles nativement avec Twig, en voici quelques-uns :FiltreDescriptionExemple TwigMet toutes les lettres en majuscules.{{ var|upper }}
Supprime toutes les balises XML.{{ var|striptags }}
Formate la date selon le format donné en argument. La variable en entrée doit être une instance deDatetime
.{{ date|date('d/m/Y') }}
Date d'aujourd'hui : {{ "now"|date('d/m/Y') }}
Insère des variables dans un texte, équivalent àprintf
.{{ "Il y a %s pommes et %s poires"|format(153, nb_poires) }}
Retourne le nombre d'éléments du tableau, ou le nombre de caractères d'une chaîne.Longueur de la variable : {{ texte|length }}
Nombre d'éléments du tableau : {{ tableau|length }}
La documentation de tous les filtres disponibles est dans la documentation officielle de Twig :http://twig.sensiolabs.org/doc/filters/index.html
.
Twig et la sécurité
Dans tous les exemples précédents, vos variables ont déjà été protégées par Twig ! Twig applique par défaut un filtre sur toutes les variables que vous affichez, afin de les protéger de balises HTML malencontreuses. Ainsi, si le pseudo d'un de vos membres contient un «<
» par exemple, lorsque vous faites{{ pseudo }}
celui-ci est échappé, et le texte généré est en réalité «mon<pseudo
» au lieu de «mon<pseudo
», ce qui poserait problème dans votre structure HTML. Très pratique ! Et donc à savoir : inutile de protéger vos variables en amont, Twig s'occupe de tout en fin de chaîne !Et dans le cas où vous voulez afficher volontairement une variable qui contient du HTML (JavaScript, etc.), et que vous ne voulez pas que Twig l'échappe, il vous faut utiliser le filtreraw
comme ceci :{{ ma_variable_html|raw }}
. Avec ce filtre, Twig désactivera localement la protection HTML, et affichera la variable en brut, quel que soit ce qu'elle contient.
Les variables globales
Symfony2 enregistre par défaut une variable globale
{{ app }}
dans Twig pour nous faciliter la vie. Voici la liste de ses attributs, qui sont donc disponibles dans tous vos templates :
Variable
|
Description
|
---|---|
{{ app.request }} |
La requête « request » qu'on a vu au chapitre précédent sur les contrôleurs.
|
{{ app.session }} |
Le service « session » qu'on a vu également au chapitre précédent.
|
{{ app.environment }} |
L'environnement courant : « dev », « prod », et ceux que vous avez définis.
|
{{ app.debug }} | True si le mode debug est activé, False sinon. |
{{ app.security }} |
Le service « security », que nous verrons plus loin dans ce cours.
|
{{ app.user }} |
L'utilisateur courant, que nous verrons également plus loin dans ce cours.
|
Bien
entendu, on peut enregistrer nos propres variables globales, pour
qu'elles soient accessibles depuis toutes nos vues, au lieu de les
injecter à chaque fois. Pour cela, il faut éditer le fichier de
configuration de l'application, comme suit :
# app/config/config.yml
# …
twig:
# …
globals:
webmaster: moi-même
Ainsi, la variable
<footer>Responsable du site : {{ webmaster }}.</footer>
Condition :
Boucle :
et pour avoir accès aux clés du tableau :
<select>
{% for valeur, option in liste_options %}
<option value="{{ valeur }}">{{ option }}</option>
{% endfor %}
</select>
Équivalent PHP :
<ul>
<?php if(count($liste_membres) > 0) {
foreach($liste_membres as $membre) {
echo '<li>'.$membre->getPseudo().'</li>';
}
} else { ?>
<li>Pas d'utilisateur trouvé.</li>
<?php } ?>
</ul>
Avec les clés :
<?php
foreach($liste_options as $valeur => $option) {
// …
}
Définition :
Une petite information sur la structure
La balise
La balise
À l'intérieur du template inclus, vous retrouvez toutes les variables qui sont disponibles dans le template qui fait l'inclusion : exactement comme si vous copiiez-colliez le contenu.
# app/config/config.yml
# …
twig:
# …
globals:
webmaster: moi-même
Ainsi, la variable
{{ webmaster }}
sera injectée dans toutes vos vues, et donc utilisable comme ceci :<footer>Responsable du site : {{ webmaster }}.</footer>
Je profite de cet
exemple pour vous faire passer un petit message. Pour ce genre de
valeurs paramétrables, la bonne pratique est de les définir non pas
directement dans le fichier de configuration
config.yml
, mais dans le fichier des paramètres, à savoir parameters.yml
. Attention, je parle bien de la valeur du paramètre, non de la configuration. Voyez par vous-mêmes.
Valeur du paramètre :
# app/config/parameters.yml
parameters:
# …
app_webmaster: moi-même
parameters:
# …
app_webmaster: moi-même
Configuration (ici, injection dans toutes les vues) qui utilise le paramètre :
# app/config/config.yml
twig:
globals:
webmaster: %app_webmaster%
twig:
globals:
webmaster: %app_webmaster%
On a ainsi séparé la valeur du paramètre, stockée dans un fichier
simple, et l'utilisation de ce paramètre, perdue dans le fichier de
configuration.
Structures de contrôle et expressions
Les structures de contrôle
Nous avons vu comment afficher quelque chose, maintenant nous allons faire des choses, avec la syntaxe
{% … %}
.
Condition : {% if %}
Exemple Twig :
{% if membre.age < 12 %}
Il faut avoir 12 ans pour ce film.
{% elseif membre.age < 18 %}
OK bon film.
{% else %}
Un peu vieux pour voir ce film non ?
{% endif %}
Il faut avoir 12 ans pour ce film.
{% elseif membre.age < 18 %}
OK bon film.
{% else %}
Un peu vieux pour voir ce film non ?
{% endif %}
Équivalent PHP :
Boucle :
{% for %}
Exemple Twig :
<ul>
{% for membre in liste_membres %}
<li>{{ membre.pseudo }}</li>
{% else %}
<li>Pas d'utilisateur trouvé.</li>
{% endfor %}
</ul>
et pour avoir accès aux clés du tableau :
<select>
{% for valeur, option in liste_options %}
<option value="{{ valeur }}">{{ option }}</option>
{% endfor %}
</select>
Équivalent PHP :
<ul>
<?php if(count($liste_membres) > 0) {
foreach($liste_membres as $membre) {
echo '<li>'.$membre->getPseudo().'</li>';
}
} else { ?>
<li>Pas d'utilisateur trouvé.</li>
<?php } ?>
</ul>
Avec les clés :
<?php
foreach($liste_options as $valeur => $option) {
// …
}
Définition : {% set %}
Exemple Twig :
{% set foo = 'bar' %}
Équivalent PHP :
<?php $foo = 'bar'; ?>
Une petite information sur la structure
{% for %}
, celle-ci définit une variable {{ loop }}
au sein de la boucle, qui contient les attributs suivants :
Variable
|
Description
|
---|---|
{{ loop.index }} |
Le numéro de l'itération courante (en commençant par 1).
|
{{ loop.index0 }} |
Le numéro de l'itération courante (en commençant par 0).
|
{{ loop.revindex }} |
Le nombre d'itérations restantes avant la fin de la boucle (en finissant par 1).
|
{{ loop.revindex0 }} |
Le nombre d'itérations restantes avant la fin de la boucle (en finissant par 0).
|
{{ loop.first }} | true si c'est la première itération, false sinon. |
{{ loop.last }} | true si c'est la dernière itération, false sinon. |
{{ loop.length }} |
Le nombre total d'itérations dans la boucle.
|
Les tests utiles
Defined
Pour vérifier si une variable existe.
Exemple Twig :
{% if var is defined %} … {% endif %}
Équivalent PHP :
<?php if(isset($var)) { }
Even
/ Odd
Pour tester si un nombre est pair / impair.
Exemple Twig :
{% for valeur in liste %}
<span class="{% if loop.index is even %}pair{% else %}
impair{% endif %}">
{{ valeur }}
</span>
{% endfor %}
<span class="{% if loop.index is even %}pair{% else %}
impair{% endif %}">
{{ valeur }}
</span>
{% endfor %}
Équivalent PHP :
<?php
$i = 0;
foreach($liste as $valeur) {
echo '<span class="';
echo $i % 2 ? 'impair' : 'pair';
echo '">'.$valeur.'</span>';
$i++;
}
$i = 0;
foreach($liste as $valeur) {
echo '<span class="';
echo $i % 2 ? 'impair' : 'pair';
echo '">'.$valeur.'</span>';
$i++;
}
La documentation de tous les tests disponibles est dans la documentation officielle de Twig.
Hériter et inclure des templates
L'héritage de template
Je vous ai fait un teaser
précédemment : l'héritage de templates va nous permettre de résoudre la
problématique : « J'ai un seul design et n'ai pas l'envie de le répéter
sur chacun de mes templates ». C'est un peu comme ce que vous devez
faire aujourd'hui avec les
include()
, mais en mieux !Le principe
Le principe est simple : vous avez un template père qui contient le design de votre site ainsi que quelques trous (appelés « blocks
» en anglais, que nous nommerons « blocs » en français) et des
templates fils qui vont remplir ces blocs. Les fils vont donc venir
hériter du père en remplaçant certains éléments par leur propre contenu.
L'avantage est que les templates fils peuvent modifier plusieurs blocs du template père. Avec la technique des
include()
, un template inclus ne pourra pas modifier le template père dans un autre endroit que là où il est inclus !
Les
blocs classiques sont le centre de la page et le titre. Mais en fait,
c'est à vous de les définir ; vous en ajouterez donc autant que vous
voudrez.
La pratique
Voici à quoi peut ressembler un template père (appelé plus communément layout). Mettons-le dans
src/OC/PlatformBundle/Resources/views/layout.html.twig
:
{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}OC Plateforme{% endblock %}</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}OC Plateforme{% endblock %}</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
Et voici un de nos templates fils. Mettons-le dans
src/OC/PlatformBundle/Resources/views/Advert/index.html.twig
:
{# src/OC/PlatformBundle/Resources/views/Advert/index.html.twig #}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}{{ parent() }} - Index{% endblock %}
{% block body %}
Notre plateforme est un peu vide pour le moment, mais cela viendra !
{% endblock %}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}{{ parent() }} - Index{% endblock %}
{% block body %}
Notre plateforme est un peu vide pour le moment, mais cela viendra !
{% endblock %}
Hériter et inclure des templates
L'héritage de template
Je vous ai fait un teaser
précédemment : l'héritage de templates va nous permettre de résoudre la
problématique : « J'ai un seul design et n'ai pas l'envie de le répéter
sur chacun de mes templates ». C'est un peu comme ce que vous devez
faire aujourd'hui avec les
include()
, mais en mieux !Le principe
Le principe est simple : vous avez un template père qui contient le design de votre site ainsi que quelques trous (appelés « blocks
» en anglais, que nous nommerons « blocs » en français) et des
templates fils qui vont remplir ces blocs. Les fils vont donc venir
hériter du père en remplaçant certains éléments par leur propre contenu.
L'avantage est que les templates fils peuvent modifier plusieurs blocs du template père. Avec la technique des
include()
, un template inclus ne pourra pas modifier le template père dans un autre endroit que là où il est inclus !
Les
blocs classiques sont le centre de la page et le titre. Mais en fait,
c'est à vous de les définir ; vous en ajouterez donc autant que vous
voudrez.
La pratique
Voici à quoi peut ressembler un template père (appelé plus communément layout). Mettons-le dans
src/OC/PlatformBundle/Resources/views/layout.html.twig
:
{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}OC Plateforme{% endblock %}</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}OC Plateforme{% endblock %}</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
Et voici un de nos templates fils. Mettons-le dans
src/OC/PlatformBundle/Resources/views/Advert/index.html.twig
:
{# src/OC/PlatformBundle/Resources/views/Advert/index.html.twig #}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}{{ parent() }} - Index{% endblock %}
{% block body %}
Notre plateforme est un peu vide pour le moment, mais cela viendra !
{% endblock %}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}{{ parent() }} - Index{% endblock %}
{% block body %}
Notre plateforme est un peu vide pour le moment, mais cela viendra !
{% endblock %}
Qu'est-ce que l'on vient de faire ?
Pour bien comprendre tous les concepts utilisés dans cet exemple très simple, détaillons un peu.
Le nom du template père
On a placé ce template dans
views/layout.html.twig
et non dans views/qqch/layout.html.twig
.
C'est tout à fait possible ! En fait, il est inutile de mettre dans un
sous-répertoire les templates qui ne concernent pas un contrôleur
particulier et qui peuvent être réutilisés par plusieurs contrôleurs.
Attention à la notation pour accéder à ce template : du coup, ce n'est
plus OCPlatformBundle:MonController:layout.html.twig
, mais OCPlatformBundle::layout.html.twig
. C'est assez intuitif, en fait : on enlève juste la partie qui correspond au répertoire MonController
. C'est ce que l'on a fait à la première ligne du template fils.
La balise {% block %}
côté père
Pour définir un « trou » (dit bloc) dans le template père, nous avons utilisé la balise
{% block %}
.
Un bloc doit avoir un nom afin que le template fils puisse modifier tel
ou tel bloc de façon nominative. La base, c'est juste de faire {% block nom_du_block %}{% endblock %}
et c'est ce que nous avons fait pour le body. Mais vous pouvez insérer
un texte par défaut dans les blocs, comme on l'a fait pour le titre.
C'est utile pour deux cas de figure :- Lorsque le template fils ne redéfinit pas ce bloc. Plutôt que de n'avoir rien d'écrit, vous aurez cette valeur par défaut.
- Lorsque les templates fils veulent réutiliser une valeur commune. Par exemple, si vous souhaitez que le titre de toutes les pages de votre site commence par « OC Plateforme », alors depuis les templates fils, vous pouvez utiliser
{{ parent() }}
qui permet d'utiliser le contenu par défaut du bloc côté père. Regardez, nous l'avons fait pour le titre dans le template fils.
La balise {% block %}
côté fils
Elle
se définit exactement comme dans le template père, sauf que cette
fois-ci on y met notre contenu. Mais étant donné que les blocs se
définissent et se remplissent de la même façon, vous avez pu deviner
qu'on peut hériter en cascade ! En effet, si l'on crée un troisième
template petit-fils qui hérite de fils, on pourra faire beaucoup de
choses.
Le modèle « triple héritage »
Pour
bien organiser ses templates, une bonne pratique est sortie du lot. Il
s'agit de faire de l'héritage de templates sur trois niveaux, chacun des
niveaux remplissant un rôle particulier. Les trois templates sont les
suivants :
- Layout général : c'est le design de votre site, indépendamment de vos bundles. Il contient le header, le footer, etc. La structure de votre site donc (c'est notre template père).
- Layout du bundle : il hérite du layout général et contient les parties communes à toutes les pages d'un même bundle. Par exemple, pour notre plateforme d'annonce, on pourrait afficher un menu particulier, rajouter « Annonces » dans le titre, etc.
- Template de page : il hérite du layout du bundle et contient le contenu central de votre page.
Nous verrons un exemple de ce triple héritage juste après.
Question : puisque le layout général ne dépend pas d'un bundle en particulier, où le mettre ?
Dans votre répertoire
/app
! En effet, dans ce répertoire, vous pouvez toujours avoir des fichiers
qui écrasent ceux des bundles ou bien des fichiers communs aux bundles.
Le layout général de votre site fait partie de ces ressources communes.
Son répertoire exact doit être app/Resources/views/layout.html.twig
.
Et pour l'appeler depuis vos templates, la syntaxe est la suivante : «
::layout.html.twig
». Encore une fois, c'est très intuitif : après avoir enlevé le nom du
contrôleur tout à l'heure, on enlève juste cette fois-ci le nom du
bundle.
Afin de
bien vous représenter l'architecture adoptée, je vous propose un petit
schéma à la figure suivante. Il vaut ce qu'il vaut, mais vous permet de
bien comprendre ce qu'on fait.
Je vous parle du bloc rouge un peu après, c'est une inclusion non pas de
template, mais d'action de contrôleur ! Il ne fait pas partie du modèle
triple héritage à proprement parler.
L'inclusion de templates
La théorie : quand faire de l'inclusion ?
Hériter, c'est bien, mais inclure, ce n'est pas mal non plus. Prenons un exemple pour bien faire la différence.
Le
formulaire pour ajouter une annonce est le même que celui pour…
modifier une annonce. On ne va pas faire du copier-coller de code, cela
serait assez moche, et puis nous sommes fainéants. C'est ici que
l'inclusion de templates intervient. On a nos deux templates
OCPlatformBundle:Advert:add.html.twig
et OCPlatformBundle:Advert:edit.html.twig
qui héritent chacun de OCPlatformBundle::layout.html.twig
.
L'affichage exact de ces deux templates diffère un peu, mais chacun d'eux inclut
OCPlatformBundle:Advert:form.html.twig
à l'endroit exact pour afficher le formulaire.
On voit bien qu'on ne peut pas faire d'héritage sur le template
form.html.twig
, car il faudrait le faire hériter une fois de add.html.twig
, une fois de edit.html.twig
,
etc. Comment savoir ? Et si un jour, nous souhaitons ne le faire
hériter de rien du tout pour afficher le formulaire tout seul dans une popup par exemple ? Bref, c'est bien une inclusion qu'il nous faut ici.La pratique : comment le faire ?
Comme toujours avec Twig, cela se fait très facilement. Il faut utiliser la fonction
{{ include() }}
, comme ceci :
{{ include("OCPlatformBundle:Advert:form.html.twig") }}
Ce code inclura le contenu du template à l'endroit de la balise. Une
sorte de copier-coller automatique, en fait ! Voici un exemple avec la
vue
add.html.twig
:
{# src/OC/PlatformBundle/Resources/views/Advert/add.html.twig #}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block body %}
<h2>Ajouter une annonce</h2>
{{ include("OCPlatformBundle:Advert:form.html.twig") }}
<p>
Attention : cette annonce sera ajoutée directement
sur la page d'accueil après validation du formulaire.
</p>
{% endblock %}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block body %}
<h2>Ajouter une annonce</h2>
{{ include("OCPlatformBundle:Advert:form.html.twig") }}
<p>
Attention : cette annonce sera ajoutée directement
sur la page d'accueil après validation du formulaire.
</p>
{% endblock %}
Et voici le code du template inclus (ici, le formulaire) :
{# src/OC/PlatformBundle/Resources/views/Advert/form.html.twig #}
{# Cette vue n'hérite de personne, elle sera incluse par d'autres vues qui,
elles, hériteront probablement du layout. Je dis « probablement » car,
ici pour cette vue, on n'en sait rien et c'est une info qui ne nous concerne pas. #}
<h3>Formulaire d'annonce</h3>
{# On laisse vide la vue pour l'instant, on la comblera plus tard
lorsqu'on saura afficher un formulaire. #}
<div class="well">
Ici se trouvera le formulaire.
</div>
{# Cette vue n'hérite de personne, elle sera incluse par d'autres vues qui,
elles, hériteront probablement du layout. Je dis « probablement » car,
ici pour cette vue, on n'en sait rien et c'est une info qui ne nous concerne pas. #}
<h3>Formulaire d'annonce</h3>
{# On laisse vide la vue pour l'instant, on la comblera plus tard
lorsqu'on saura afficher un formulaire. #}
<div class="well">
Ici se trouvera le formulaire.
</div>
À l'intérieur du template inclus, vous retrouvez toutes les variables qui sont disponibles dans le template qui fait l'inclusion : exactement comme si vous copiiez-colliez le contenu.
L'inclusion de contrôleurs
La théorie : quand inclure des contrôleurs ?
Voici
un dernier point à savoir absolument avec Twig, un des points les plus
puissants dans son utilisation avec Symfony2. On vient de voir comment
inclure des templates : ceux-ci profitent des variables du template qui
fait l'inclusion, très bien.
Seulement
dans bien des cas, depuis le template qui fait l'inclusion, vous
voudrez inclure un autre template, mais vous n'avez pas les variables
nécessaires pour lui. Restons sur l'exemple de notre plateforme
d'annonces, dans le schéma précédent je vous ai mis un bloc rouge :
considérons que dans cette partie du menu, accessible sur toutes les
pages même hors de la liste des annonces, on veut afficher les 3
dernières annonces.
C'est
donc depuis le layout général qu'on va inclure non pas un template —
nous n'aurions pas les variables à lui donner —, mais un contrôleur. Le
contrôleur va créer les variables dont il a besoin, et les donner à son
template, pour ensuite être inclus là où on le veut !
La pratique : comment le faire ?
Au risque de me répéter : cela se fait très simplement !
Du côté du template qui fait l'inclusion, à la place de la fonction
{{ include() }}
, il faut utiliser la fonction {{ render() }}
, comme ceci :
{{ render(controller("OCPlatformBundle:Advert:menu")) }}
Ici,
OCPlatformBundle:Advert:menu
n'est pas un template mais une action de contrôleur, c'est la syntaxe qu'on utilise dans les routes, vous l'aurez reconnue.
Voici par exemple ce qu'on mettrait dans le layout :
{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}OC Plateforme{% endblock %}</title>
</head>
<body>
<div id="menu">
{{ render(controller("OCPlatformBundle:Advert:menu")) }}
</div>
{% block body %}
{% endblock %}
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}OC Plateforme{% endblock %}</title>
</head>
<body>
<div id="menu">
{{ render(controller("OCPlatformBundle:Advert:menu")) }}
</div>
{% block body %}
{% endblock %}
</body>
</html>
Et du côté du contrôleur, on ajoute la méthode
menuAction()
très classique, qui retourne une réponse avec le template menu
comme contenu :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AdvertController extends Controller
{
// ...
public function menuAction()
{
// On fixe en dur une liste ici, bien entendu par la suite
// on la récupérera depuis la BDD !
$listAdverts = array(
array('id' => 2, 'title' => 'Recherche développeur Symfony2'),
array('id' => 5, 'title' => 'Mission de webmaster'),
array('id' => 9, 'title' => 'Offre de stage webdesigner')
);
return $this->render('OCPlatformBundle:Advert:menu.html.twig', array(
// Tout l'intérêt est ici : le contrôleur passe
// les variables nécessaires au template !
'listAdverts' => $listAdverts
));
}
}
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AdvertController extends Controller
{
// ...
public function menuAction()
{
// On fixe en dur une liste ici, bien entendu par la suite
// on la récupérera depuis la BDD !
$listAdverts = array(
array('id' => 2, 'title' => 'Recherche développeur Symfony2'),
array('id' => 5, 'title' => 'Mission de webmaster'),
array('id' => 9, 'title' => 'Offre de stage webdesigner')
);
return $this->render('OCPlatformBundle:Advert:menu.html.twig', array(
// Tout l'intérêt est ici : le contrôleur passe
// les variables nécessaires au template !
'listAdverts' => $listAdverts
));
}
}
Et enfin, un exemple de ce que pourrait être le template
menu.html.twig
:
{# src/OC/PlatformBundle/Resources/views/Advert/menu.html.twig #}
{# Ce template n'hérite de personne,
tout comme le template inclus avec {{ include() }}. #}
<ul class="nav nav-pills nav-stacked">
{% for advert in listAdverts %}
<li>
<a href="{{ path('oc_platform_view', {'id': advert.id}) }}">
{{ advert.title }}
</a>
</li>
{% endfor %}
</ul>
{# Ce template n'hérite de personne,
tout comme le template inclus avec {{ include() }}. #}
<ul class="nav nav-pills nav-stacked">
{% for advert in listAdverts %}
<li>
<a href="{{ path('oc_platform_view', {'id': advert.id}) }}">
{{ advert.title }}
</a>
</li>
{% endfor %}
</ul>
Commentaires
Enregistrer un commentaire