TP n°5 - Gabarits (templates) Twig pour créer les pages HTML
Ajout de gabarits Twig dans l’application ToDo

Table des matières

1. Introduction

Cette séance va permettre d’expérimenter l’application des concepts présentés dans le cours qui précède, à travers la mise en œuvre d’interfaces HTML pour une application Symfony avec Twig, sur la base de l’application fil-rouge ToDo.

Nous nous concentrons sur le moteur de gabarits (templates) Twig, le composant de Symfony permettant la génération des pages Web de l’application. En utilisant Twig, on peut notamment standardiser la structure des pages du site avec un jeu de gabarits permettant d’unifier le contenu de toutes les pages.

Dans cette séance, nous faisons référence à des rudiments d’HTML, en nous appuyant sur le travail effectué en autonomie dans la séquence de travail précédente.

2. Étape 1 : Mise en place de la séance

2.1. TODO Préparation du répertoire de travail

Vous allez dupliquer l’arborescence du projet PHP obtenu à la fin de la séance précédente, pour travailler sur une nouvelle version.

Vous pourrez ainsi faire évoluer le code, et revenir en arrière si besoin, en comparant l’état à la fin de la séance prédente, avec l’état courant.

  1. Effectuez les opérations suivantes pour dupliquer le dossier :

    cd "$HOME/CSC4101"
    cp -r tp-02 tp-05
    cd tp-05
    cd todo-app
    
  2. Ensuite, dans ce nouveau projet, on va réinitialiser les rouages du cadriciel Symfony avec Composer :

    cd "$HOME/CSC4101/tp-05/todo-app"
    rm -fr composer.lock symfony.lock var/cache/ vendor/ .project
    symfony composer install
    

    Confirmez la génération de fichiers pour Docker (on ne s’en servira pas tout de suite, mais pourquoi ne pas les avoir… le rôle de Docker ne sera pas évoqué en cours, mais vous pouvez en parler à vos encadrants de TP).

Cette étape est nécessaire car Symfony s’appuie sur une mécanique sophistiquée de mise en cache du code de l’application (dans var/cache/), pour assurer des performances maximales. Malheureusement, si on duplique un projet, une partie de ce cache a tendance à devenir incohérente (présence de chemins d’accès « en dur », etc.).

Il est donc préférable de réinitialiser le projet radicalement : à un état le plus « propre » possible. On fait ensuite réinstaller par Composer les bibliothèques du cadriciel Symfony (installées dans vendor/), et reconfigurer certains fichiers de configuration associés.

2.2. TODO Chargement du nouveau projet dans l’IDE

Vous allez travailler sur un nouveau projet dans le workspace dans l’IDE Eclipse, importé depuis ce nouveau répertoire de travail.

  1. Pour les utilisateurs de l’IDE Eclipse, supprimez les anciennes infos du projet Eclipse :

    cd "$HOME/CSC4101/tp-05/todo-app"
    rm -fr .project .settings/
    
  2. Importez dans votre IDE cette nouvelle version du projet Symfony Todo sur laquelle vous allez maintenant travailler.

    Dans Eclipse vous pouvez importer ce nouveau projet dans le même workspace que le précédent, mais avec un nom distinctif (par exemple « todo-tp-5 »).

    Si besoin, vous pourrez comparer le code des deux projets « todo-tp-5 » et « todo-tp-2 ». Mais pour l’instant, et pour éviter de vous mélanger, nous vous conseillons de fermer le projet de la séance précédente (menu Project / Close …).

3. Étape 1 : Ajout de gabarits Twig dans l’application ToDo

L’objectif de cette étape est d’étudier comment fonctionne la mise en place d’un gabarit standard pour différentes pages d’une même application, et de pratiquer la syntaxe du langage Twig.

Nous allons maintenant travailler sur code de l’application de gestion de tâches (ToDo) qui nous sert de fil-rouge, en réalisant la mise en œuvre de la génération de pages avec des gabarits.

3.1. Principe de la génération du HTML grâce au moteur de rendu des gabarits

En utilisant des gabarits, pour produire du HTML, le code des classes contrôleurs de notre application n’aura plus besoin de manipuler des chaînes de caractères à concaténer.

Il se contente de construire une représentation minimaliste des ressources à afficher dans les pages, puis de demander au moteur de rendu Twig d’en faire un rendu HTML.

Twig va injecter cette représentation dans des gabarits qui contiennent un squelette de HTML, et dans lequel sont prévus des emplacements pour insérer les différents champs de cette représentation minimaliste.

3.2. TODO Modification de l’affichage des tâches

Vous travaillez sur le contrôleur réalisant l’affichage des tâches TodoController pour qu’il utilise les gabarits Twig.

Vous allez donc faire en sorte qu’il n’y ait plus de traces de HTML dans le code PHP de la classe contrôleur. À la place on devra trouver l’appel à une méthode render() qui utilise un fichier Twig et un tableau associatif avec des variables.

Vous pouvez vous inspirer du code qui avait été généré par make:controller pour TagController, et qui utilise Twig.

  1. Vous pouvez par exemple ajouter un nouveau fichier index.html.twig dans le répertoire templates/, qui contient les fichiers gabarit de Twig utilisés par la méthode render() :

    {% extends 'base.html.twig' %}
    
    {% block title %}Welcome!{% endblock %}
    
    {% block body %}
    <h1>Welcome</h1>
    
        <p>{{ welcome }}</p>
    
    {% endblock %} {# body #}
    

    Si la syntaxe des gabarits Twig n’estreconnue immédiatement par Eclipse, vous pouvez installer le plugin Twig pour Eclipse, via le Eclipse Marketplace.

    Un plugin Jinja pourrait probablement faire l’affaire également.

  2. Ensuite, vous pouvez modifier la méthode d’affichage de la page d’accueil de l’application pour qu’elle utilise ce gabarit :

    // src/Controller/TodoController.php
    
    // ...
    
    #[Route('/todo')]
    class TodoController extends AbstractController
    {    
         #[Route('/', name: 'home', methods: ['GET'])]
         public function indexAction(): Response
         {
             return $this->render('index.html.twig',
                                  [ 'welcome' => "Bonne utilisation de la todo list" ]
                            );
         }
    
  3. Examinez la façon avec laquelle les données sont insérées pour construire la page affichable (HTML), au travers de l’inclusion de variables comme welcome, qui va être insérée dans la cible {{ welcome }}.
  4. Modifiez ce message et rechargez la page pour voir l’affichage changer.

On va voir plus loin que Twig ne permet pas seulement d’injecter des valeurs dans des champs à l’intérieur d’un fichier HTML. Il permet aussi d’effectuer des traitements pour factoriser des motifs, ou gérer des traitements conditionnels, par exemple.

3.3. TODO Observation de la structure des pages standardisée

  1. Observez le code source de la page HTML générée par Twig, dans le navigateur Web (Ctrl-U, ou menu bouton droit, puis « Code source de la page »).

    Vous y trouvez du code HTML ressemblant à :

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Welcome!</title>
            <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
    
    
    
                </head>
        <body>
            <h1>Welcome</h1>
    
        <p>Bonne utilisation de la todo list</p>
    
    
    <div id="sfwdtbdd3ea" class="sf-toolbar sf-display-none" role="region" aria-label="Symfony Web Debug Toolbar">...
    

    Ignorez la partie du <div class="sf-toolbar ..."> en fin de page, qui correspond à l’affichage de la barre d’outils Symfony.

    Comparez avec le code du gabarit templates/index.html.twig ci-dessus.

    Vous devriez voir la partie utile du HTML provenant du bloc twig body ({% block body %}...{% endblock %}).

    Mais d’où provient le reste du HTML de ce qui précède : <html>, <head>, … </head>, jusqu’à <body> ?

  2. Observez le contenu du fichier source du gabarit templates/base.html.twig

    Vous y voyez justement tous ces éléments du gabarit HTML de base.

    Les différents fichiers Twig définissent des blocs, avec les balises Twig {% block ... %} et {% endblock %}. Ici, justement le gabarit de base base.html.twig défnii un bloc Twig body par défaut, vide : {% block body %}{% endblock %} (il n’y a rien entre la balise ouvrante « block » et la balise fermante « endblock »).

    L’instruction {% extends 'base.html.twig' %} en en-tête de index.html.twig permet de de mettre en place un système de surcharge des blocs de ce gabarit de base, comme autant de motifs permettant de construire une factorisation et une réutilisation pour la structure des pages HTML.

    Vous devriez comprendre le principe de surcharge des blocs, comme la surcharge de méthodes dans l’orienté objet.

    Le rendu du gabarit fonctionne comme un compilateur : il part du gabarit de base (base.html.twig), qui est « étendu » (surchargé) par les gabarits spécialisés, comme index.html.twig, ici. Si un bloc Twig (comme body) est surchargé, c’est la version surchargée qui remplace la version de base.

    C’est donc le contenu fourni entre les balises « block body » et « endblock » de index.html.twig qui va s’insérer dans le gabarit de base.

    twig-blocks-overloading.png

  3. De la même façon, comprenez-vous le rôle du bloc « title » , dans templates/base.html.twig ?

Avec ce mécanisme de surcharge de blocs, on peut définir une structure générale, puis la personnaliser, faire des cas particuliers.

On peut ainsi décliner un gabarit général en spécificités relatives à chacune des sections ou des pages particulières de l’application.

Pour les Web designers, la conception des gabarits consiste donc à chercher des motifs factorisables (généralisables), ou spécialisables, et s’apparente à la conception orientée objet qu’on applique pour la programmation.

4. TODO Étape 2 : Utilisation de la barre d’outils Symfony pour la mise au point

L’objectif de cette étape est de découvrir les fonctionnalités de la barre d’outils de Symfony pour les gabarits.

Comme on l’a déjà vu, pendant le développement de l’application, l’environnement Symfony est réglé en mode dev. En conséquence, en bas de chaque page Web générée par Symfony se trouve une barre d’outils permettant d’accéder à de nombreux outils facilitant la mise au point.

Testez l’affichage des pages de l’application dans lequelles les gabarits Twig sont maintenant utilisés.

Consultez les informations affichées dans la barre d’outils Symfony en bas de pages, où vous devriez trouver une nouvelle icône correspondant aux gabarits Twig.

L’outil du Profiler correspondant à la génération des gabarits Twig donne des informations sur ce qui se passe sous le capot.

Le Rendering Call Graph est particulièrement intéressant en montrant l’enchaînement des générations des différents blocs surchargés.

Pour l’affichage de /todo/ il devrait donner quelque chose du style :

main 11.73ms/100%
└ index.html.twig 11.44ms/98%
│ └ base.html.twig 10.98ms/94%
│   └ index.html.twig::block(title)
│   └ base.html.twig::block(stylesheets) 10.94ms/93%
│   └ base.html.twig::block(javascripts)
│   └ index.html.twig::block(body)
└ @WebProfiler/Profiler/toolbar_js.html.twig
  └ @WebProfiler/Profiler/toolbar.html.twig
  │ └ @WebProfiler/Profiler/cancel.html.twig::block(toolbar)
  │   └ @WebProfiler/Profiler/toolbar_item.html.twig
  └ @WebProfiler/Profiler/toolbar.css.twig

On voit l’enchaînement :

  1. index.html.twig inclut base.html.twig
  2. comme base.html.twig contient le rendu de 4 blocs : title, stylesheet, javascripts et body, on les voit apparaître successivement. Mais :
    • stylesheet, javascripts sont notés comme étant ceux de base.html.twig. Normal, ils n’ont pas été surchargés.
    • par contre, title et body proviennent de index.html.twig car ce template les a redéfinis, pour les besoins de cette page particulière de l’application.
  3. Le reste des gabarits de @WebProfiler correspond aux outils du Profiler inclus dans la page.

5. Étape 3 : Remplacement du code HTML par des gabarits, dans ToDo

À l’image de ce qui a été montré ci-desssus pour la page d’accueil, on va modifier les différentes méthodes du contrôleur TodoController, pour utiliser les gabarits, au lieu d’une génération de chaînes de caractère HTML dans le code PHP.

5.1. TODO Étape 3-a : Consultation d’une collection de tâches

Procédez aux opérations suivantes :

  1. Créez un sous-répertoire templates/todo/ et à l’intérieur, un nouveau gabarit index.html.twig, contenant :

    {% extends 'base.html.twig' %}
    
    {% block title %}Welcome!{% endblock %}
    
    {% block body %}
    <h1>Todo index</h1>
    
    <ul>
      {% for todo in todos %}
      <li>{{ todo.title }}</li>
      {% endfor %} {# todos #}
    </ul>
    
    {% endblock %} {# body #}
    

    Notez qu’on utilise {{ }} pour afficher la valeur d’une variable, alors qu’on utilise {% %} pour exécuter des instructions Twig.

  1. Modifiez le code de la méthode du contrôleur TodoController pour utiliser ce gabarit :

    /**
     * Lists all todo entities.
     */
    #[Route('/list', name: 'todo_list', methods: ['GET'])]
    #[Route('/index', name: 'todo_index', methods: ['GET'])]
    public function listAction(ManagerRegistry $doctrine): Response
    {
            $entityManager= $doctrine->getManager();
            $todos = $entityManager->getRepository(Todo::class)->findAll();
    
            // dump($todos);
    
            return $this->render('todo/index.html.twig',
                          [ 'todos' => $todos ]
                    );
    }
    

    Le contrôleur passe en argument au rendu Twig la variable todos, qui contient une collection d’entités Doctrine (vérifiez en dé-commentant l’appel à dump()).

    Notez la différence par rapport à la version précédente, qui faisait un foreach($todos as $todo) dans le code PHP. Ccette fois, c’est dans le gabarit Twig que se produit l’algorithme d’itération foreach sur l’affichage de chaque élément d’une collection, avec l’instruction {%for ITEM in COLLECTION %}.

    Twig peut alors accéder « nativement » aux propriétés des instances de classes PHP présentes dans la collection : {{ todo.title }} se traduira en un appel à Todo:getTitle().

  2. Testez l’affichage de la page /todo/list, donc le code source HTML doit bien contenir les éléments du gabarit de base
  3. Modifiez <li>{{ todo.title }}</li> dans templates/todo/index.html.twig.

    Vous pouvez par exemple afficher <li>Title: {{ todo.title }}</li>, ou ajouter l’identifiant des taches : <li>({{ todo.id }}) {{ todo.title }}</li>.

    Vérifiez que le simple rechargement de la page dans le navigateur permet de voir le résultat.

    Il n’y a plus forcément besoin de modifier le code PHP. On peut se séparer le travail entre adaptations du code PHP et du contenu des pages dans Twig. Modularisation souhaitable pour améliorer la qualité.

  4. Pour vérifier qui fait quoi, essayez de modifier le code de Todo::getTitle() pour ajouter, par exemple un caractère « ! » au début du titre de chaque tâche :

    public function getTitle(): ?string
    {
        return '!' . $this->title;
    }
    

    Rechargez la page Web : la modification est appliquée… mais alors elle s’applique aussi à symfony console app:list-todos

On voit bien sur cet exemple que les gabarits Twig qui construisent les vues de notre application, sont câblés correctement par Symfony avec les données du modèle objet de Doctrine.

En cas de changement, il convient de se mettre d’accord : est-ce qu’une modification de l’application doit porter sur le modèle de données ou sur la présentation Web (ou les deux). On sait ainsi où intervenir : PHP, ou Twig.

5.2. TODO Étape 3-b : Amélioration du rendu de la liste de tâche, sous forme de tableau

On va modifier encore le gabarit templates/todo/index.html.twig pour afficher toutes les propriétés des tâches dans un tableau.

Au lieu d’une liste à puces simple, on veut obtenir un tableau HTML du type :

<table class="table">
    <thead>
        <tr>
            <th>Id</th>
            <th>Todo</th>
            <th>Completed</th>
            <th>Created</th>
            <th>Updated</th>
        </tr>
    </thead>
    <tbody>

        <tr>
            <td>1</td>
            <td>apprendre les bases de PHP</td>
            <td>1</td>
            <td>2018-08-06 14:03:57</td>
            <td>2018-08-06 14:03:57</td>
        </tr>

        ...

    </tbody>
</table>

Modifiez le code du gabarit templates/todo/index.html.twig autour du foreach, pour afficher ainsi les différentes propriétés de chaque tâche présente dans todos.

Notez que les dates peuvent être affichées avec une instruction Twig d’affichage d’une variable, du type : {{ todo.created ? todo.created|date('Y-m-d H:i:s') : '' }}, qui signifie :

  • si l’attribut created est défini (on utilise la contruction de l’opérateur ternaire «  ? :  », plutôt qu’un if/then/else), alors on va afficher sa valeur sous forme de date avec un certain format d’affichage (on utilise un « filtre » d’affichage de valeur avec l’opérateur {{ ... | FORMAT }} - cf. https://twig.symfony.com/doc/3.x/filters/date.html)
  • sinon, afficher une chaîne vide

On ne vous fournit pas le squelette à copier/coller, cette fois. Il faut un peu démarrer la réflexion sur le code. Ce n’est pas très complexe, mais prenez le temps de relire attentivement les instructions.

5.3. TODO Étape 3-c : Utilisation d’un gabarit pour l’affichage d’une instance de tâche

L’objectif de cette étape est de mieux comprendre le fonctionnement de la surcharge des blocs dans les gabarits Twig, et d’introduire path().

Soyez attentifs, cette étape est un peu moins triviale… méfiez-vous du copier/coller.

L’affichage d’une tâche d’identifiant 1 est réalisée sur le chemin http://localhost:8000/todo/1.

Modifiez maintenant l’affichage d’une seule tâche, en vous inspirant des extraits suivants :

  1. adaptez la méthode du contrôleur qui va gère les requêtes HTTP entrantes, qui devrait ressembler à ceci :

    /**
     * Finds and displays a todo entity.
     */
    #[Route('/{id}', name: 'todo_show', requirements: ['id' => '\d+'], methods: ['GET'])]
    public function showAction(Todo $todo): Response
    {
        return $this->render('todo/show.html.twig',
            [ 'todo' => $todo ]
        );
    }
    
    

    Pour l’instant on laisse un peu de côté l’explication de la « magie » qui permet de récupérer l’instance de Todo grâce à doctrine, dans ce code (cf. « Aller plus loin » optionnel).

  2. ajoutez un nouveau gabarit templates/todo/show.html.twig (en recopiant son « cousin » todo/index.html.twig, par exemple), contenant par exemple la génération d’un tableau HTML du type :

    {# ... #} 
      {% block body %}
          <h1>Todo show</h1>
    
             {% dump todo %}
    
          <table class="table">
              <tbody>
                  <tr>
                      <th>Id</th>
                      <td>{{ todo.id }}</td>
                  </tr>
                  <tr>
                      <th>Title</th>
                      <td>{{ todo.title }}</td>
                  </tr>
                  ...
              </tbody>
          </table>
    
          <a href="{{ path('todo_index') }}">back to list</a>
    
      {% endblock %} {# body #} 
    {# ... #} 
    

    Le lien « back to list » en bas de page contient une balise HTML de lien <a href="">...</a> tout à fait classique pour accéder à une autre page de l’application.

    La valeur de son attribut href (l’URL cible du lien), est définie à {{ path('todo_index') }}. C’est la même construction {{ ... }} Twig pour afficher la valeur d’une variable. Elle va juste faire appel à une fonction de Symfony pour Twig : path( ) .

    La fonction path( ) prend en premier argument le nom d’une route de Symfony (ici todo_index), et renvoie le chemin de cette route qui sera la cible du lien (ici ce sera /todo/index). Ce sont les noms et chemins définis par le Routeur de Symfony vus plus haut.

    Vérifiez que l’affichage fonctionne bien, et que le lien est naviguable, en corrigeant le nom de la route si nécessaire.

Est-ce que l’affichage fonctionne bien ? Est-ce que la barre d’outils Symfony est toujours affichée ?

Si elle ne s’affiche pas, utilisez les outils du développeur Web dans le navigateur pour voir si quelque chose n’est pas cassé :

  1. Consultez le code source de la page, et vérifiez qu’elle contient bien du HTML bien formé… avec tout ce qui va bien….
  2. Y a-t-il les éléments nécessaire à l’affichage de la barre d’outils Symfony dans la page ?

Indice pour réparer l’affichage : il est nécessaire de bien remettre en place cette génération d’HTML complète, en faisant comme dans le gabarit todo/index.html.twig : il faut bien l’inclusion du gabarit de base : {% extends 'base.html.twig' %} au début du gabarit, même si nous ne l’avons pas inclus dans le code à copier/coller, ci-dessus. Méfiez-vous des {# ... #} !

Une fois que c’est fait, la barre d’outils Symfony doit se rafficher correctement.

Bravo : vous avez compris comment fonctionne la surcharge des gabarits. Vous savez maintenant comment factoriser des blocs de contenu des pages, et les spécialiser dans certaines pages d’une application.

5.4. TODO Étape 3-d : Ajout d’un lien de navigation entre liste des tâches et affichage d’une tâche

L’objectif de cette étape est de mieux comprendre l’utilité de la fonction path().

On va ajouter dans la consultation de la collection des tâches (/todo/list), un lien pointant vers la page de consultation de chacune de ses tâches.

Ajoutez dans le tableau des tâches (todo/index.html.twig), une dernière colonne pour contenir des liens navigables :

<thead>
  <tr>
    ...
    <th> &nbsp;</th>
  </tr>
</thead>
<tbody>
  ...
  <tr>
    ...
    <td><a href="{{ path('todo_show', {'id': todo.id}) }}">show</a></td>
  </tr>
</tbody>

Dans ces balises HTML de lien, l’attribut href doit pointer vers l’URL d’affichage correspondant à la tâche courante. Cette URL varie, pour chaque tâche à afficher, puisqu’elle contient l’identifiant de la tâche.

Cette fois encore, la fonction path( ) doit prendre en premier argument le nom de la route. Mais elle doit aussi recevoir la valeur des arguments de cette route, qui rendent l’URL dynamique.

Ici, la route todo_show attend un argument ’id’, comme cela est défini dans l’attribut de l’annotation #Route('/{id}' de TodoController::showAction().

On passe les arguments qu’elle attend via un tableau associatif en syntaxe Twig (façon dictionnaire Python) : id vaut todo.id. Voilà pour {{ path('todo_show', {'id': todo.id}) }}.

Votre interface est navigable dans les deux sens : de la collection (index) aux entités (show), et retour.

Bravo : vous connaissez presque tous les éléments fondamentaux pour programmer une interface Web en consultation avec Twig.

6. Étape 4 : Utilisation de dump() pour faciliter la mise au point

En cours de développement, pour faciliter le débogage (debug), nous avons vu que vous pouvez introduire l’affichage d’un objet en utilisant la fonction dump() dans le code PHP, par exemple à l’intérieur d’une méthode d’action contrôleur, avant l’appel à la méthode render :

$todos = $em->getRepository(Todo::class)->findAll();
dump($todos);

Mais vous pouvez aussi utiliser la fonction dump() à l’intérieur d’un gabarit Twig, dans une instruction dump de Twig, appelée avec :

{% dump todo %}

Dans les deux cas, la présence des informations de debug correspondantes aux appels à dump() se retrouve dans la console Symfony, derrière l’icône en forme de « cible » qui apparaît alors dans la barre d’outils du développeur Symfony.

Attention : {% dump todo %} est différent de {{ dump(todo) }} : la première est une instruction Twig (précédée de « {% », comme un for), alors que la seconde affiche la valeur des informations de debug (une chaîne de caractère contenant du code HTML, tel que renvoyé par l’appel à dump(todo)) inséré au milieu du rendu de la page (comme pour tout accès à une variable via « {{ ... }} »). La deuxième pollue l’affichage, quand la première cache juste les infos de debug derrière la « cible » de la barre d’outils Symfony.

7. TODO Étape 5 : Affichage des tâches terminées

L’objectif de cette étape est de mettre en forme les tâches terminées de façon différente des tâches à faire, grâce aux instructions Twig dans les gabarits.

On souhaite par exemple afficher les tâches terminées comme étant barrées, dans la liste des tâches.

C’est l’étape finale qui est le moins guidée. Bon courage.

Vous pouvez utiliser la balise HTML <del> pour ce faire.

Vous exploiterez la primitive if du langage de gabarits de Twig, en vous référant à la documentation de référence de Twig.

Modifiez le gabarit d’affichage de la liste des tâches (index.html.twig) pour intégrer ce changement

Dans les données d’exemple de l’application fournies, seule la tâche « terminer le hp 2-3 » « apprendre les bases de PHP » a le statut terminé ;-).

8. Conclusion

Comme vous l’aurez maintenant compris, dans une application Symfony, une partie des algorithmes peuvent être programmés dans le code PHP. C’est particulièrement vrai pour ce qui concerne le modèle de données, avec Doctrine. On peut par exemple changer l’ordre de chargement des données, comme on l’a vu dans une séance précédente, au niveau de la surcharge de la méthode findAll() dans le Repository.

Mais on peut aussi programmer certains comportements dans les gabarits Twig, avec sa syntaxe propre, par exemple pour faire varier seulement la présentation des données.

Il faudra faire un choix : appliquer des traitements dans les couches modèle et traitements en PHP, ou dans la couche présentation en TWig… tout dépend des compétences des différents développeurs (PHP vs Twig ?), mais aussi des contraintes : performances, encombrement mémoire, factorisation. À vous de décider.

9. TODO Étape 6 : Mise en place des gabarits Twig dans votre projet

Vous pouvez maintenant mettre en pratique ce que nous venons de voir, sur les gabarits Twig, dans votre projet.

Le principe est de structurer des pages Web avec des gabarits, plutôt que de faire du HTML « à la main ».

Poursuivez la séance en déroulant les étapes du guide de réalisation du projet.

Vous la continuerez en travail hors présentiel sur votre projet, d’ici la prochaine séance de TP (Notez le label « Après_TP_5 » dans la section du guide de réalisation).

10. Évaluation

À l’issue de cette séance, vous savez :

  • construire des pages d’une application à partir de gabarits (templates) Twig
  • vous comprenez le principe de surcharge de gabarits pour rendre la structure des pages uniforme
  • vous savez utiliser des primitives du langage Twig telles que if ou for
  • vous savez tisser des liens vers d’autres pages avec path()
  • vous savez examiner des éléments de diagnostic (pour déverminage / debug) avec dump()

11. Pour aller plus loin (optionnel)

11.1. Chargement « automagique » d’une instance en consultation grâce à l’Entity Value Resolver

Observez le code de TodoController::showAction().

Comprenez-vous comment est obtenue l’instance de Todo, $todo qui est récupérée en paramètre par cette méthode ?

Vous avez bien vu que l’identifiant id est spécifié dans l’annotation définissant la route (on précise même que c’est un entier), qui correspond à l’attribut todo.id dans la génération des liens avec path() dans le gabarit de liste des tâches.

Peut-on instancier en mémoire un objet $todo chargé depuis la base de données, une fois qu’on connaît son identifiant ?

On peut utiliser le code suivant, qui utilise explicitement Doctrine, comme dans le TP précédent :

$todo = $em->getRepository(Todo::class)->find($id);

Mais comme une application Symfony finit typiquement par contenir ce genre de code presque systématiquement, les développeurs du framework ont intégré ce mécanisme dans la classe Contrôleur via le mécanisme Entity Value Resolver, de façon a rendre cela « automagique ».

Ce mécanisme, sur lequel reviendra plus tard, instancie automatiquement une classe de notre modèle de données Doctrine, chargée depuis la base de données à partir d’une valeur d’identifiant fournie, lorsqu’il n’y a pas d’ambiguïté.

La documentation Symfony vous donnera plus d’infos, à partir de Automatically Fetching Objects (EntityValueResolver).

Author: Olivier Berger (TSP)

Date: 2025-08-19 Tue 16:10

Emacs (Org mode)