Archives Wild Code School
Symfony

03 - Symfony : Création de la page d’accueil

Quête 4 sur 35

Objectifs

  • ✅ Créer un contrôleur
  • ✅ Implémenter une route
  • ✅ Appeler un template Twig

Pré-requis

​ Terminer la quête suivante :

Quêtes liées
title
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
<?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>'
        );
    }
}

Attention

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.

↗
En apprendre plus sur la classe Response de Symfony

Tu trouveras sur la même page quelques lignes sur l'objet Request (autre objet fondamental), ce qui n'est pas un mal 😉.

symfony.com

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é).

Attention

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 :

php
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>'
        );
    }
}
php
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".

Info

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.

↗
Créer son premier contrôleur en Symfony

Déclarer la route associée à un contrôleur.

symfony.com
↗
🎥 Les routes en vidéos

Vidéo sur le routing configuré en attribut.

symfonycasts.com

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 :

php
#[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).

Info

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.

twig
{% 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".

Attention

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.

↗
Symfony Best Practices

Le guide des meilleures pratiques en Symfony, définitivement un MUST READ !

symfony.com

🎯 Un petit quizz pour vérifier que tu as bien tout compris

quiz
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 DefaultController et étend le AbstractController de 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 un return $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. 🙂