Revenons à notre blog. Faites en sorte d'avoir sous la main le contrôleur que l'on a réalisé au chapitre précédent. Le but ici est de créer tous les
templates que l'on a utilisés depuis le contrôleur, ou du moins leur squelette. Étant donné que l'on n'a pas encore la vraie liste des articles, on va faire avec des variables vides : ça va se remplir par la suite, mais le fait d'employer des variables vide va nous permettre dès maintenant de construire le
template.
Pour encadrer tout ça, nous allons utiliser le modèle d'héritage sur trois niveaux :
layout général,
layout du
bundle et
template.
Layout général
La théorie
Comme évoqué plus tôt, le
layout est la structure HTML de notre site avec des blocs aux endroits stratégiques pour permettre aux
templates qui hériteront de ce dernier de personnaliser la page. On va ici créer une structure simple ; je vous laisse la personnaliser si besoin est. Pour les blocs, pareil pour l'instant, on fait simple : un bloc pour le
body et un bloc pour le titre.
Encore une fois, vous devez personnaliser tout ça ! Je ne suis pas là pour faire le blog à votre place, juste pour vous guider. Si vous ne pratiquez pas de votre côté en ajoutant, supprimant et améliorant tout ce que l'on voit ici, vous serez vite perdu ! Je vous fais confiance, ne faites pas que lire, codez.

Je vais également en profiter pour introduire l'utilisation de ressources CSS/JS/etc dans Symfony2. Cela se fait très bien avec la balise
asset de Twig, qui va chercher vos ressources dans le répertoire /web. Regardez simplement comment elle est utilisée dans l'exemple et vous saurez l'utiliser de façon basique.
La pratique
Commençons par faire le layout général de l'application, la vue située dans le répertoire
app/. Voici le code exemple que je vous propose :
Code : HTML & Django 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | {# app/Resources/views/layout.html.twig #}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{% block title %}Sdz{% endblock %}</title>
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('css/bootstrap.css') }}" type="text/css" />
{% endblock %}
</head>
<body>
<div class="container">
<div id="header" class="hero-unit">
<h1>Mon Projet Symfony2</h1>
<p>Ce projet est propulsé par Symfony2, et construit grâce au tutoriel du siteduzero.</p>
<p><a class="btn btn-primary btn-large" href="http://www.siteduzero.com/tutoriel-3-517569-symfony2.html">
Lire le tutoriel »
</a></p>
</div>
<div class="row">
<div id="menu" class="span3">
<h3>Le blog</h3>
<ul class="nav nav-pills nav-stacked">
<li><a href="{{ path('sdzblog_accueil') }}">Accueil du blog</a></li>
<li><a href="{{ path('sdzblog_ajouter') }}">Ajouter un articlce</a></li>
</ul>
</div>
<div id="content" class="span9">
{% block body %}
{% endblock %}
</div>
</div>
<hr>
<footer>
<p>The sky's the limit © 2012 and beyond.</p>
</footer>
</div>
</body>
{% block javascripts %}
{# Ajoutez ce javascript si vous comptez vous servir des fonctionnalités du bootstrap Twitter #}
<script type="text/javascript" src="{{ asset('js/bootstrap.js') }}"></script>
{% endblock %}
</html>
|
J'ai surligné les parties qui contiennent un peu de Twig :
- ligne 8 : création du bloc « title » avec « Sdz » comme contenu par défaut ;
- lignes 11 : appel du CSS situé dans /web/css/bootstrap.css ;
- lignes 29 et 30 : utilisation de la fonction {{ path }} pour faire des liens vers d'autres routes ;
- lignes 34 et 35 : création du bloc « body » sans contenu par défaut.
Et voilà, nous avons notre
layout général ! Pour pouvoir tester nos pages, il faut maintenant s'attaquer au layout du bundle.
Layout du bundle
La théorie
Comme on l'a dit, ce
template va hériter du
layout général, rajouter la petite touche perso au
bundle Blog, puis se faire hériter à son tour par les
templates finaux. En fait, il ne contient pas grand-chose. Laissez courir votre imagination, mais moi, je ne vais rajouter qu'une balise
<h1>, vous voyez ainsi le mécanisme et pouvez personnaliser à votre sauce.
La seule chose à laquelle il faut faire attention, c'est au niveau du nom des blocs. Une bonne pratique consiste à préfixer le nom des blocs par le nom du
bundle courant. Regardez le code et vous comprendrez.
La pratique
Extrait du fichier
src/Sdz/BlogBundle/Resources/views/layout.html.twig :
Code : HTML & Django 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | {# src/Sdz/BlogBundle/Resources/views/layout.html.twig #}
{% extends "::layout.html.twig" %}
{% block title %}
Blog - {{ parent() }}
{% endblock %}
{% block body %}
{# On définit un sous-titre commun à toutes les pages du bundle, par exemple #}
<h1>Blog</h1>
<hr>
{# On gère les messages flash de façon global pour tout le bundle #}
{% for key, flash in app.session.getFlashes() %}
<div class="alert alert-{{ key }}">
{{ flash }}
</div>
{% endfor %}
{# On définit un nouveau block, que les vues du bundle pourront étendre #}
{% block sdzblog_body %}
{% endblock %}
{% endblock %}
|
On a ajouté un
<h1> dans le bloc « body » puis créé un nouveau bloc qui sera personnalisé par les
templates finaux. On a préfixé le nom du nouveau
block pour le
body afin d'avoir un nom unique pour notre
bundle.
Les templates finaux
La théorie
Pas trop de théorie ici, il ne reste plus qu'à hériter et personnaliser les
templates.
Blog/index.html.twig
C'est le
template de la page d'accueil. On va faire notre première boucle sur la variable
{{ articles }}. Cette variable n'existe pas encore, on va modifier le contrôleur juste après.
Code : HTML & Django 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | {# src/Sdz/BlogBundle/Resources/views/Blog/index.html.twig #}
{% extends "SdzBlogBundle::layout.html.twig" %}
{% block title %}
Accueil - {{ parent() }}
{% endblock %}
{% block sdzblog_body %}
<h2>Liste des articles</h2>
<ul>
{% for article in articles %}
<li>
<a href="{{ path('sdzblog_voir', {'id': article.id}) }}">{{ article.titre }}</a>
par {{ article.auteur }},
le {{ article.date|date('d/m/Y') }}
</li>
{% else %}
<li>Pas (encore !) d'articles</li>
{% endfor %}
</ul>
{% endblock %}
|
Pas grand-chose à dire, on a juste utilisé les variables et expressions expliquées plus haut dans ce chapitre.
Afin que cette page fonctionne, il nous faut modifier l'action
indexAction() du contrôleur pour passer une variable
{{ articles }} à cette vue. Pour l'instant, voici juste de quoi se débarrasser de l'erreur :
Code : PHP | <?php
// src/Sdz/BlogBundle/Controller/BlogController.php
// Dans l'action indexAction() :
return $this->render('SdzBlogBundle:Blog:index.html.twig', array(
'articles' => array()
));
|
Si vous avez bien ajouté le CSS de Twiter, voici ce à quoi cela devrait ressembler :
Vous voulez voir des articles au lieu du message pas très drôle ? Je suis trop bon, voici un tableau d'articles à ajouter temporairement dans la méthode
indexAction(), que vous pouvez passer en paramètre à la méthode
render(). C'est un tableau pour l'exemple, par la suite il faudra bien sûr récupérer les articles depuis la base de données

.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | <?php
// src/Sdz/BlogBundle/Controller/BlogController.php
// ...
public function indexAction()
{
// ...
// Les articles :
$articles = array(
array('titre' => 'Mon weekend a Phi Phi Island !', 'id' => 1, 'auteur' => 'winzou', 'contenu' => 'Ce weekend était trop bien. Blabla...', 'date' => new \Datetime()),
array('titre' => 'Repetition du National Day de Singapour', 'id' => 2, 'auteur' => 'winzou', 'contenu' => 'Bientôt prêt pour le jour J. Blabla...', 'date' => new \Datetime()),
array('titre' => 'Chiffre d\'affaire en hausse', 'id' => 3, 'auteur' => 'M@teo21', 'contenu' => '+500% sur 1 an, fabuleux. Blabla...', 'date' => new \Datetime())
);
// Puis modifiez la ligne du render comme ceci, pour prendre en compte nos articles :
return $this->render('SdzBlogBundle:Blog:index.html.twig', array(
'articles' => $articles
));
}
|
Rechargez la page, et profitez du résultat.
Attention, on vient de définir des articles en brut dans le contrôleur, mais c'est uniquement pour l'exemple d'utilisation de Twig ! Ce n'est bien sûr pas du tout une façon correcte de le faire, par la suite nous les récupérerons depuis la base de données.
Blog/voir.html.twig
Il ressemble beaucoup à
index.html.twig sauf qu'on passe à la vue une variable
{{ article }} contenant un seul article, et non plus une liste d'articles. Voici un code par exemple :
Code : HTML & Django 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | {# src/Sdz/BlogBundle/Resources/views/Blog/voir.html.twig #}
{% extends "SdzBlogBundle::layout.html.twig" %}
{% block title %}
Lecture d'un article - {{ parent() }}
{% endblock %}
{% block sdzblog_body %}
<h2>{{ article.titre }}</h2>
<i>Par {{ article.auteur }}, le {{ article.date|date('d/m/Y') }}</i>
<div class="well">
{{ article.contenu }}
</div>
<p>
<a href="{{ path('sdzblog_accueil') }}" class="btn">
<i class="icon-chevron-left"></i>
Retour à la liste
</a>
<a href="{{ path('sdzblog_modifier', {'id': article.id}) }}" class="btn">
<i class="icon-edit"></i>
Modifier l'article
</a>
<a href="{{ path('sdzblog_supprimer', {'id': article.id}) }}" class="btn">
<i class="icon-trash"></i>
Supprimer l'article
</a>
</p>
{% endblock %}
|
Et l'adaptation du contrôleur bien évidemment :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | <?php
// src/Sdz/BlogBundle/Controller/BlogController.php
// ...
public function voirAction($id)
{
// ...
$article = array(
'id' => 1,
'titre' => 'Mon weekend a Phi Phi Island !',
'auteur' => 'winzou',
'contenu' => 'Ce weekend était trop bien. Blabla...',
'date' => new \Datetime()
);
// Puis modifiez la ligne du render comme ceci, pour prendre en compte l'article :
return $this->render('SdzBlogBundle:Blog:voir.html.twig', array(
'article' => $article
));
}
|
Ainsi que le résultat visuel
http://localhost/Symfony/web/app_dev.php/blog/article/1 :
Blog/modifier.html.twig et ajouter.html.twig
Ceux-ci contiennent une inclusion de
template. En effet, rappelez-vous, j'avais pris l'exemple d'un formulaire utilisé pour l'ajout mais également la modification. C'est notre cas ici, justement. Voici donc le fichier
modifier.html.twig :
Code : HTML & Django 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | {# src/Sdz/BlogBundle/Resources/views/Blog/modifier.html.twig #}
{% extends "SdzBlogBundle::layout.html.twig" %}
{% block title %}
Modifier un article - {{ parent() }}
{% endblock %}
{% block sdzblog_body %}
<h2>Modifier un article</h2>
{% include "SdzBlogBundle:Blog:formulaire.html.twig" %}
<p>
Vous éditez un article déjà existant,
ne le changez pas trop pour éviter
aux membres de ne pas comprendre
ce qu'il se passe.
</p>
<p>
<a href="{{ path('sdzblog_voir', {'id': article.id}) }}" class="btn">
<i class="icon-chevron-left"></i>
Retour à l'article
</a>
</p>
{% endblock %}
|
Le
template ajouter.html.twig lui ressemble énormément, je vous laisse donc le faire.
Quant à
formulaire.html.twig, on ne sait pas le faire encore car il demande des notions de formulaire, mais faisons déjà sa structure pour le moment :
Code : HTML & Django | {# src/Sdz/BlogBundle/Resources/views/Blog/formulaire.html.twig #}
{# Cette vue n'hérite de personne, elle sera inclue par d'autres vues qui, elles, hériteront sûrement du layout. #}
{# Je dis "sûrement" car, ici pour cette vue, on n'en sait rien et c'est une info qui ne nous concerne pas. #}
<h3>Formulaire d'article</h3>
{# Ici on laisse vide la vue pour l'instant, on la comblera plus tard lorsque saura afficher un formulaire. #}
<div class="well">
Ici se trouvera le formulaire.
</div>
|
Une chose importantes ici : dans ce
template, il n'y a aucune notion de bloc, d'héritage, etc. Ce
template est un électron libre : vous pouvez l'inclure depuis n'importe quel autre
template. Il faut seulement lui donner un « with » afin que, ici, la variable du formulaire
{{ form }} soit disponible.
Et le résultat visuel
http://localhost/Symfony/web/app_dev.php/blog/modifier/1 :
Conclusion
Et voilà, nous avons généré presque tous nos
templates. Bien sûr, ils sont encore un peu vides car on ne sait pas utiliser les formulaires ni récupérer les articles depuis la base de données. Mais vous savez maintenant les réaliser et c'était une étape importante ! Je vais vous laisser créer les
templates manquants ou d'autres afin de vous faire la main. Bon code !