03 - Symfony : Création de la page d’accueil
Objectifs
- ✅ Créer un contrôleur
- ✅ Implémenter une route
- ✅ Appeler un template Twig
Pré-requis
Terminer la quête suivante :
Introduction
À la fin de cette quête, ton Wild Series commencera enfin à prendre forme ! Tu seras capable d’afficher la toute première page.
User stories 📋
en tant que visiteur, je souhaite récupérer les données d'une série
en tant que visiteur, je souhaite récupérer la liste des séries
en tant que contributeur, je souhaite ajouter une série
In progress 🤸
en tant qu'utilisateur je souhaite accéder à la page d'accueil
Doing 🏗️
création des contrôleurs ProramController et DefaultController
Done ✅
initialisation du projet Symfony
Sommaire
Créer le premier contrôleur
Un contrôleur en Symfony n'est pas différent d'un contrôleur en MVC : c'est tout simplement une classe.
Elle doit étendre Symfony\Bundle\FrameworkBundle\Controller\AbstractController. Cette classe va également contenir des méthodes (appelées actions), qui seront appelées via le mécanisme de routing.
Par convention, le nom de ces classes est suffixé par Controller, par exemple, ForumController. Tu en déduiras facilement le nom du fichier : ForumController.php.
Mais où doit-on les mettre, ces contrôleurs ?
Dans l'absolu, un contrôleur peut vivre n'importe où. Certaines librairies fournissent même leurs propres contrôleurs, se trouvant donc dans le dossier vendor/nom_de_librairie/.
Cependant, Symfony est configuré par défaut pour accueillir ceux que tu vas créer pour ton projet, dans le dossier src/Controller/ (et éventuellement dans des sous-dossiers).
Maintenant que tu sais tout ça, et pour s’entraîner, nous allons créer une page qui, plus tard, listera toutes tes séries.
Rends-toi dans le répertoire wild-series/ que tu as initialisé lors de la quête précédente et crée dans le répertoire src/Controller/ le contrôleur ProgramController.php suivant :
<?php
// src/Controller/ProgramController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class ProgramController extends AbstractController
{
public function index(): Response
{
return new Response(
'<html><body>Wild Series Index</body></html>'
);
}
}
N'oublie pas la déclaration du namespace ! Les classes de contrôleur doivent se trouver dans le namespace App\Controller.
L'objet Response
Ok, tu as fait ton contrôleur. Mais il y a peut-être une chose que tu n'as pas comprise en copiant ce code : quel est cet objet Response qui est retourné avec du HTML à l'intérieur ?
Eh bien c'est un objet qui représente une réponse HTTP complète. Dans une réponse HTTP, on peut trouver des headers, un code de réponse (2xx, 3xx, ...) et éventuellement un contenu (HTML, JSON, ...). C'est pareil pour l'objet Symfony\Component\HttpFoundation\Response de Symfony.
Le travail d'un contrôleur de Symfony est de retourner un objet de la classe Response ! Tout le temps. Quoi qu'il arrive. C'est une notion fondamentale à assimiler si tu veux comprendre le fonctionnement du framework.
Ici notre réponse HTML est "écrite en dure", mais ça changera par la suite.
Tu trouveras sur la même page quelques lignes sur l'objet Request (autre objet fondamental), ce qui n'est pas un mal 😉.
Implémenter la route
Voilà, tu as fait ton premier contrôleur, mais tu ne sais pas encore vraiment s'il fonctionne... Il va falloir le lier à une route pour tester tout ça ! Une route, finalement, ce n'est que de la configuration. Tu peux généralement la configurer de plusieurs manières, au format annotation, YAML, XML, PHP... ou via les attributs (recommandé).
Les attributs (attributes en anglais) sont une nouvelle syntaxe apportée par PHP8 et disponible depuis Symfony 6. Avant cela, la configuration utilisait les annotations. Tu risques encore de trouver beaucoup de documentation avec cette ancienne syntaxe. Il existe donc plusieurs manières de configurer les routes, tu trouveras toutes ces informations dans la documentation, mais nous allons nous focaliser sur la nouvelle manière de faire avec les attributs.
Le routing via les attributs
Les attributs sont des morceaux de codes utiles pour définir des configurations. Ils s'écrivent sous la forme #[attributeName(key: value)]. Même si l'attribut commence par un '#' dans ce cas particulier il n'est pas considéré comme un commentaire. Ils viennent remplacer les annotations qui n'étaient pas natives de PHP mais reposaient sur des librairies tierces, mais l'idée est la même. Quelque part dans le code de Symfony, des classes sont écrites pour venir interpréter ces attributs et exécuter des actions en conséquence, mais c'est toutes la "magie" du framework, il effectue du travail pour te simplifier la vie sans que tu aies besoin de savoir ce qu'il fait en détail 🤓.
Ajoute désormais ton nouvel attribut #[Route]. Pour ce premier exemple, la syntaxe avec les annotations est également fournie afin que tu puisses comparer les deux (c'est aussi le cas sur la documentation de Symfony). Ensuite nous resterons uniquement sur les attributs :
use Symfony\Component\Routing\Attribute\Route;
Class ProgramController extends AbstractController
{
#[Route('/program/', name: 'program_index')]
public function index(): Response
{
return new Response(
'<html><body>Wild Series Index</body></html>'
);
}
}use Symfony\Component\Routing\Annotation\Route;
Class ProgramController extends AbstractController
{
/**
* @Route("/program/", name="program_index")
*/
public function index(): Response
{
return new Response(
'<html><body>Wild Series Index</body></html>'
);
}
}Lance ton serveur symfony (symfony server:start) et ouvre la route http://localhost:8000/program/ qui devrait renvoyer une page blanche avec écrit "Wild Series index".
Note: le paramètre name de la route est facultatif mais extrêmement utile. Il sera détaillé plus tard mais il sert notamment pour générer une URL dynamiquement à partir d'un nom de route. Le premier paramètre, quant à lui, définit l'URL et est obligatoire.
Déclarer la route associée à un contrôleur.
Vidéo sur le routing configuré en attribut.
Appeler un template Twig
Voilà, on a une page, mais on aimerait bien appeler une vue Twig plutôt que de mettre tout le HTML à la main dans l'objet Response... (car ça ne respecte pas les principes de séparation du MVC entre la vue et le contrôleur !)
Eh bien tu seras content d'apprendre que Twig est présent dans ton installation de Symfony !
Tu n'as plus qu'à mettre à jour ta méthode index() dans ton contrôleur ProgramController :
#[Route('/program/', name: 'program_index')]
public function index(): Response
{
return $this->render('program/index.html.twig', [
'website' => 'Wild Series',
]);
}
Et créer ta vue templates/program/index.html.twig associée (dans Symfony, les vues se placent dans un dossier templates/ en dehors de src/ et Twig est préconfiguré pour aller chercher les fichiers ici).
Tu vois qu'un layout base.html.twig est disponible dans templates/. Tu vas pouvoir y faire référence pour chacun de tes templates dans une logique d'héritage.
{% extends 'base.html.twig' %}
{% block title %}Wild Series{% endblock %}
{% block body %}
<h1>{{ website }} index</h1>
{% endblock %}
C'est tout bon ? Est-ce que tu es en train de te dire "mais c'est bizarre, on m'a dit qu'un contrôleur devait retourner un objet Response, et pourtant j'ai bien l'impression que je retourne le render d'un "Twig" ?
Attention, dans un contrôleur $this->render() renvoie bien un objet Response, et si tu en doutes, fais un [ctrl+clic gauche] sur le nom de la méthode dans ton IDE !
Ici {{ website }} est passé en contexte depuis le contrôleur à ta vue. Pour l'exemple, sa valeur est égale à “Wild Series”. Par conséquent si tu actualises ta page, ta vue à la route /program/ affiche "Wild Series index".
Tu vois peut-être une page sur un fond coloré mais ne te soucie pas du CSS pour le moment, nous en reparlerons très vite dans une prochaine quête.
Le guide des meilleures pratiques en Symfony, définitivement un MUST READ !
🎯 Un petit quizz pour vérifier que tu as bien tout compris
false|||false|||true
# Le contrôleur retourne ...
[] Un objet Twig
[x] Un objet Response
[] Un objet Request
[] Un string
[] Rien
# Quelle méthode est recommandée pour configurer le routing ?
[] PHP
[] YAML
[] Annotations
[x] Attributes
[] XML
# L'URL dans l'attribut #[Route()] est :
[x] Obligatoire
[] Facultative
# Le paramètre name dans l'attribut #[Route()] est :
[] Obligatoire
[x] Facultatif
# Selon les « Best practices », que recommande la documentation de Symfony pour nommer les fichiers Twig ?
[] camelCase.html.twig
[x] snake_case.html.twig
[] kebab-case.html.twig
[] UpperCamelCase.html.twig
> [Use Snake Case for Template Names and Variables](https://symfony.com/doc/6.4/best_practices.html#templates)
👆 **MUST READ** 🤓
💪 Challenge
La page d'accueil de ton site 🏡
Lors des étapes précédentes, tu as créé la page d'index de tes séries. Mais qu’en est-il de ta page d'accueil ?
-
Crée un nouveau contrôleur
DefaultController -
Crée une méthode
index()et une route en attribut nommée app_index qui devra répondre à une requête sur l'url/(la page par défaut de ton site finalement).Elle devra afficher un titre
<h1>contenant "Bienvenue !" grâce à un template Twig nommé index.html.twig à la racine. Pense à étendre base.html.twig mais ne te soucie pas du CSS, tu t’en chargeras lors d’une prochaine quête !
Critères de validation
-
Il y a un fichier DefaultController.php dans src/Controller de l'arborescence.
-
Ce fichier comporte une classe
DefaultControlleret étend leAbstractControllerde base de Symfony. -
La route sur
/est faite en attribut et est nommée app_index. -
Le méthode
index()du contrôleur se finit par unreturn $this->render('path_vers_un_twig');. -
Le fichier Twig index.html.twig comprend un titre h1 "Bienvenue !".
-
L'URL http://localhost:8000/ est fonctionnelle et le titre s'affiche. 🙂