28 - Symfony : Twig component
Objectifs
- ✅ Créer une navbar via un Twig component
- ✅ Afficher les 3 derniers épisodes dans une sidebar ou dans le footer
Introduction
User stories 📋
In progress 🤸
en tant que visiteur, je souhaite accéder aux catégories depuis la barre de navigation
Doing 🏗️
Intégrer un contrôleur dans le template Twig de la navbar
Done ✅
en tant que visiteur, je souhaite avoir accès à un formulaire d'inscription afin de pouvoir me créer un compte
Sommaire
Imbriquer le contrôleur

Depuis le début de la conception de ton Wild Series, tu te demandes comment tu vas bien pouvoir ajouter la liste des catégories dans la barre de navigation.
Techniquement, tu pourrais ajouter dans TOUTES les méthodes de TOUS tes contrôleurs : 'categories' => $categories
Techniquement, tu pourrais ajouter dans TOUTES les méthodes de TOUS tes... oui en effet, on doit beaucoup se répéter, ce n’est pas DRY !
Et si un développeur oubliait de l’ajouter lors de la création d’une prochaine méthode ?
La meilleure alternative sera plutôt de passer par le système de component dans Twig. Il faut voir cela comme un "super" include d'une vue twig, qui ne se contente pas d'afficher que l'HTML, mais peut aller récupérer dynamiquement des données au passage. Pour cela, il faut tout d'abord l'installer :
Installer le composant
composer require symfony/ux-twig-component
Créer un component Twig
Un component Twig est une classe PHP. Tu pourrais la créer à la main mais comme souvent avec Symfony, tu vas utiliser le maker (de nouvelles commnandes sont apparues suite à l'installation du twig-component). Lance la commande suivante et répond aux questions.
symfony console make:twig-component
Pour la première question, appelle ton composant Navbar. Pour la seconde, choisis "no" (option par défaut) quand il te demande si tu veux que ce composant soit un LiveComponent (tu verras cela dans une prochaine quête).
Le maker t'informe alors qu'il a créé deux fichiers :
- src/Twig/Components/Navbar.php (la classe PHP Navbar dans un nouveau dossier src/Twig/Components)
- templates/components/Navbar.html.twig (la vue Twig correspondante dans un nouveau dossier templates/components)
Côté PHP
Ouvre le fichier src/Twig/Components/Navbar.php
<?php
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent]
final class Navbar
{
}
Tu vois une classe vide, dans le namespace App\Twig\Components.
Au dessus de la classe, tu as un nouvel attribut #[AsTwigComponent]. C'est cet attribut qui permet à Symfony de comprendre que nous avons ici un composant relié à une vue du même nom et qui s'appelle donc components/Navbar.html.twig
Ce que tu veux faire, c'est récupérer automatiquement les catégories à chaque fois que tu souhaites afficher ta navbar. Il y a donc besoin (en plus d'afficher le HTML de ta nav) de faire une requête en base de données pour récupérer ces catégories, puis de construire le HTML qui va les afficher. Tu vas faire cela dans un dropdown Bootstrap, UIkit ou Pico CSS.
Premièrement, tu dois pouvoir accéder au Repository CategoryRepository (sans cela, il serait difficile de créer un menu dynamique des catégories). Comme pour les services, tu vas passer par le __construct() pour le récupérer.
<?php
namespace App\Twig\Components;
use App\Repository\CategoryRepository;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent()]
final class Navbar
{
public function __construct(
private CategoryRepository $categoryRepository
) {
}
}
Ensuite, il te faut une méthode qui va récupérer les categories (idéalement par ordre alphabétique, c'est plus sympa), donc getCategories().
Le nom de la méthode doit toujours commencer par get pour le bon fonctionnement.
<?php
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
use App\Repository\CategoryRepository;
#[AsTwigComponent()]
final class Navbar
{
public function __construct(
private CategoryRepository $categoryRepository
) {
}
public function getCategories(): array
{
return $this->categoryRepository->findBy([], ['name' => 'ASC']);
}
}
Côté component Twig
Le principe de fonctionnement est en deux parties. Première partie, la vue Twig et seconde partie, l'appel de cette vue dans une autre vue twig (par exemple base.html.twig).
Première partie : création de la vue du composant
La vue du component Twig a été générée par le maker, rends-toi sur le fichier templates/components/Navbar.html.twig.
<div{{ attributes }}>
<!-- component html -->
</div>
Tu as une <div{{ attributes }}> vide. Le {{ attributes }} permet de charger la configuration stimulus (sur laquelle s'appuie Symfony UX, pour rappel).
Dans cette <div>, que tu peux modifier en un autre tag HTML si tu le souhaites, tu vas avoir accès aux getters créés dans la classe reliée à cette vue, donc ta classe App\Twig\Components\Navbar
Nous allons boucler sur le tableau reçu du component PHP this.categories.
Profitons-en pour expliquer this.categories côté Twig.
La variable this.categories fait référence à getCategories(). this pour le composant Navbar et categories qui va aller chercher le getter de la propriété du même nom, soit getCategories().
C'est le côté magique de Symfony.
<li{{ attributes }} class="nav-item dropdown">
<a
class="nav-link dropdown-toggle"
href="#"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false">
Categories
</a>
<ul class="dropdown-menu">
{% for category in this.categories %}
<li>
<a
class="dropdown-item"
href="{{ path('app_category_show', {'categoryName': category.name}) }}">
{{ category.name }}</a>
</li>
{% endfor %}
</ul>
</li>
Au delà du code HTML nécessaire à créer un dropdown dans une navbar bootstrap, tu vois que tu peux récupérer le retour de ta méthode getCategories() de ton component, en utilisant this.categories. La syntaxe change un peu par rapport à ce que tu as l'habitude de manipuler, car il faut bien rajouter le this sinon il ne reconnait pas la variable. Par contre, inutile d'ajouter "get" devant "categories", Twig le fait tout seul.
Seconde partie : intégration de la vue dans la navbar
Maintenant que tu as créé ce morceau de vue, tu dois l'inclure dans ta navbar. Rends-toi sur le code de ta navbar et fais appel à la vue Twig de la première partie.
{# fichier où se trouve ta navbar #}
<nav class="navbar navbar-expand-lg">
// ...
{{ component('Navbar') }}
// ...
</nav>
Inclus le composant (qui correspond uniquement au dropdown, au bon endroit dans ta navbar. Une fois fait, réactualise ta page, tu devrais voir les catégories apparaître dans le dropdown, bravo !
Récapitulons !
- Tu crées ton fichier PHP dans
src/Twig/Components/Navbar.php - Tu crées tes méthodes
__construct()etgetCategories()danssrc/Twig/Components/Navbar.php - Tu crées ta page Twig
Navbar.html.twigdanstemplates\components\Navbar.html.twiget tu intègres ton code pour afficher ton dropdown comme tu le souhaites. - Tu fais appel dans ta vue de navbar à ton component
{{ component('Navbar') }}(ou<twig:NavBar />)
Pour aller plus loin !
Il est possible d'intégrer un component dans un autre component. Par exemple, il est possible d'avoir un component qui affiche tous les épisodes mais en se basant sur le design d'un component affichant un épisode.
💪 Challenge
Une fois ta navbar terminée, et pour mettre en pratique, crée un nouveau composant LastEpisode dont le but sera d'afficher les derniers épisodes créés dans la base. Tu devras les afficher dans une balise HTML <aside> sur toutes tes pages (au dessus du footer, ou en sidebar comme tu préfères en fonction de ton design).
Les trois cards d'épisode devront afficher le titre de l'épisode, le numéro, la saison et la série.
Critères de validation
- La navbar affiche les catégories dans un dropdown
- Un aside affiche les trois derniers épisodes créés dans l'application (via un Twig Component)