• 30 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 5/13/19

Les contrôleurs avec Symfony

Log in or subscribe for free to enjoy all this course has to offer!

Ah, le contrôleur ! Vous le savez, c'est lui qui contient toute la logique de notre site Internet. Cependant, cela ne veut pas dire qu'il contient beaucoup de code. En fait, il ne fait qu'utiliser des services, des modèles et appeler des templates. Finalement, c'est un chef d'orchestre qui se contente de faire la liaison entre tout le monde.

Nous verrons dans ce chapitre ses droits, mais aussi son devoir ultime : retourner une réponse !

Le rôle du contrôleur

Retourner une réponse

Je vous l'ai dit de nombreuses fois depuis le début de ce cours, et Fabien vient de le rappeler en introduction : le rôle du contrôleur est de retourner une réponse.

Mais concrètement, qu'est-ce que cela signifie, « retourner une réponse » ?

Souvenez-vous, Symfony s'est inspiré des concepts du protocole HTTP. Il existe dans Symfony les classes Request et Response. Retourner une réponse signifie donc tout simplement : instancier un objet Response, disons $response, et faire un return $response.

Voici le contrôleur le plus simple qui soit, c'est le contrôleur qu'on avait créé dans un des chapitres précédents. Il dispose d'une seule méthode, nommée « index », et retourne une réponse qui ne contient que « Hello World ! » :

<?php

// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;

class AdvertController
{
  public function indexAction()
  {
    return new Response("Hello World !");
  }
}

Et voilà, votre contrôleur remplit parfaitement son rôle !

Quand je parle de requête et réponse HTTP, ce sont des choses très concrètes que vous devez bien appréhender. Pour cela, je vous conseille vivement l'outil de développement de Chrome qui est très sympa pour les visualiser. Ouvrez une page web, faites bouton droit > Inspecter l'élément, puis rendez-vous dans l'onglet Réseau (ou network). Ensuite, actualisez la page pour que Chrome capture la requête HTTP qu'il envoie ainsi que la réponse HTTP retournée par le serveur web. Le résultat est présenté dans la figure suivante.

Visualisation d'une requête HTTP et sa réponse sous Chrome
Visualisation d'une requête HTTP et de sa réponse sous Chrome

Vous voyez donc tous les entêtes de la requête, qui nous permettront de construire la réponse la plus adaptée. Et dans les entêtes de la réponse ici, vous avez ceux que Symfony inclut par défaut. Il est intéressant par exemple de voir l'entête "X-Debug-Token-Link" qui contient l'URL vers le Profiler de votre page (accessible d'habitude via la toolbar en bas de vos pages), en mode "dev" uniquement bien sûr.

Alors évidemment, vous n'irez pas très loin en sachant juste cela. C'est pourquoi la suite de ce chapitre est découpée en deux parties :

  • Les objets Request et Response qui vont vous permettre de construire une réponse en fonction de la requête ;

  • Les services de base qui vont vous permettre de réaliser tout le travail nécessaire pour préparer le contenu de votre réponse.

Manipuler l'objet Request

Les paramètres de la requête

Heureusement, toutes les requêtes que l'on peut faire sur un site Internet ne sont pas aussi simples que notre « Hello World ! ». Dans bien des cas, une requête contient des paramètres : l'id d'une annonce à afficher, le nom d'un membre à chercher dans la base de données, etc. Les paramètres sont la base de toute requête : la construction de la page à afficher dépend de chacun des paramètres en entrée.

Ces paramètres, nous savons déjà les gérer, nous l'avons vu dans le chapitre sur le routeur. Mais voici un petit rappel.

Les paramètres contenus dans les routes

Tout d'abord côté route, souvenez-vous, on utilisait déjà des paramètres. Prenons l'exemple de la routeoc_advert_view :

<?php
// src/Controller/AdvertController.php

/**
 * @Route("/view/{id}", name="oc_advert_view", requirements={"id" = "\d+"})
 */
public function view($id)
{
  return new Response("Affichage de l'annonce d'id : ".$id);
}

Ici, le paramètre{id}de la requête est récupéré par la route, qui le transforme en argument $id pour le contrôleur. Vous connaissez donc la première manière de récupérer des arguments : ceux contenus dans la route.

Les paramètres hors routes

En plus des paramètres de routes que nous venons de voir, vous pouvez récupérer les autres paramètres de l'URL, disons, « à l'ancienne ». Prenons par exemple l'URL /advert/view/5?tag=developer, il nous faut bien un moyen pour récupérer ce paramètre tag : c'est ici qu'intervient l'objet Request.

Pour récupérer la requête depuis un contrôleur, il faut l'injecter comme nous avions injecté des objets. Pour cela, ajoutez un argument à votre méthode avec le typehint Request comme ceci :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request; // Nouveau use
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class AdvertController extends Controller
{
  /**
   * @Route("/view/{id}", name="oc_advert_view", requirements={"id" = "\d+"})
   */
  public function view($id, Request $request)
  {
    // Vous avez accès à la requête HTTP via $request
  }
}

Comment est-ce possible ? C'est en réalité le Kernel qui s'occupe de cela, car c'est lui qui dispose de la requête. Après avoir demandé au routeur quel contrôleur exécuter, et avant de l'exécuter effectivement, il regarde si l'un des arguments de la méthode est typé avec Request . Si c'est le cas, il ajoute la requête aux arguments avant d'exécuter le contrôleur.

Maintenant que nous savons récupérer la requête, voici comment récupérer les paramètres contenus dans l'URL :

<?php
public function view($id, Request $request)
{
  // On récupère notre paramètre tag
  $tag = $request->query->get('tag');

  return new Response(
    "Affichage de l'annonce d'id : ".$id.", avec le tag : ".$tag
  );
}

Et vous n'avez plus qu'à tester le résultat :/advert/view/2?tag=developer.

Nous avons utilisé $request->query pour récupérer les paramètres de l'URL passés en GET, mais vous savez qu'il existe d'autres types de paramètres :

Type de paramètres

Méthode Symfony

Méthode traditionnelle

Exemple

Variables d'URL

$request->query

$_GET

$request->query->get('tag')

Variables de formulaire

$request->request

$_POST

$request->request->get('tag')

Variables de cookie

$request->cookies

$_COOKIE

$request->cookies->get('tag')

Variables de serveur

$request->server

$_SERVER

$request->server->get('REQUEST_URI')

Variables d'entête

$request->headers

$_SERVER['HTTP_*']

$request->headers->get('USER_AGENT')

Paramètres de route

$request->attributes

n/a

On utilise $id dans les arguments de la méthode, mais vous pourriez également écrire  $request->attributes->get('id')

Avec cette façon d'accéder aux paramètres, vous n'avez pas besoin de tester leur existence. Par exemple, si vous écrivez  $request->query->get('sdf') alors que le paramètre sdf n'est pas défini dans l'URL, cela vous retournera une chaîne vide, et non une erreur.

Les autres méthodes de l'objet Request

Heureusement, l'objet Request ne se limite pas à la récupération de paramètres. Il permet de savoir plusieurs choses intéressantes à propos de la requête en cours, voyons ses possibilités.

Récupérer la méthode de la requête HTTP

Pour savoir si la page a été récupérée via GET (clic sur un lien) ou via POST (envoi d'un formulaire), il existe la méthode $request->isMethod() :

<?php
if ($request->isMethod('POST'))
{
  // Un formulaire a été envoyé, on peut le traiter ici
}
Savoir si la requête est une requête AJAX

Lorsque vous utiliserez AJAX dans votre site, vous aurez sans doute besoin de savoir, depuis le contrôleur, si la requête en cours est une requête AJAX ou non. Par exemple, pour renvoyer du XML ou du JSON à la place du HTML. Pour cela, rien de plus simple !

<?php
if ($request->isXmlHttpRequest())
{
  // C'est une requête AJAX, retournons du JSON, par exemple
}
Toutes les autres

Pour avoir la liste exhaustive des méthodes disponibles sur l'objet Request, je vous invite à lire l'API de cet objet sur le site de Symfony. Vous y trouverez toutes les méthodes, même si nous avons déjà survolé les principales.

Manipuler l'objet Response

Décomposition de la construction d'un objet Response

Pour que vous compreniez bien ce qu'il se passe en coulisses lors de la création d'une réponse, voyons la manière longue et décomposée de construire et de retourner une réponse. Pour l'exemple, traitons le cas d'une page d'erreur 404 (page introuvable), en modifiant notre méthode  view()  :

<?php
// src/Controller/AdvertController.php

public function view($id, Request $request)
{
  // On crée la réponse sans lui donner de contenu pour le moment
  $response = new Response();

  // On définit le contenu
  $response->setContent("Ceci est une page d'erreur 404");

  // On définit le code HTTP à « Not Found » (erreur 404)
  $response->setStatusCode(Response::HTTP_NOT_FOUND);

  // On retourne la réponse
  return $response;
}

N'hésitez pas à tester cette page, l'URL est /advert/view/2 si vous avez gardé les mêmes routes depuis le début.

Je ne vous le cache pas : nous n'utiliserons jamais cette méthode longue ! Lisez plutôt la suite.

Réponses et vues

Généralement, vous préférerez que votre réponse soit contenue dans une vue tel que le préconise l'architecture MVC. Heureusement pour nous, la classe dont nous héritons dispose d'un raccourci : la méthode$this->render(). Elle prend en paramètres le nom du template et ses variables, puis s'occupe de tout : créer la réponse, lui passer le contenu du template, et la retourner. La voici en action :

<?php
// src/Controller/AdvertController.php

public function view($id, Request $request)
{
  $tag = $request->query->get('tag');

  // On utilise le raccourci : il crée un objet Response
  // Et lui donne comme contenu le contenu du template
  return $this->render(
    'Advert/view.html.twig',
    ['id'  => $id, 'tag' => $tag]
  );
}

Et voilà, en une seule ligne, c'est bouclé ! C'est comme cela que nous générerons la plupart de nos réponses. Finalement, l'objet Response est utilisé en coulisses, nous n'avons pas à le manipuler directement dans la plupart des cas.

N'oubliez pas de créer la vue associée bien entendu :

{# templates/Advert/view.html.twig #}

<!DOCTYPE html>
<html>
<head>
  <title>Affichage de l'annonce {{ id }}</title>
</head>
<body>
  <h1>Hello Annonce n°{{ id }} !</h1>
  <p>Tag éventuel : {{ tag }}</p>
</body>
</html>

Si vous ne deviez retenir qu'une seule chose de cette section, c'est bien cette méthode$this->render(), car c'est vraiment celle que nous utiliserons en permanence. ;)

Réponse et redirection

Vous serez sûrement amenés à faire une redirection vers une autre page. Or notre contrôleur est obligé de retourner une réponse. Comment gérer une redirection ? Eh bien, vous avez peut-être évité le piège, mais une redirection est une réponse HTTP.

Pour simplifier la construction d'une réponse faisant une redirection, il existe l'objet RedirectResponse qui étend l'objet Response que nous connaissons bien, en lui ajoutant l'entête HTTP Location qu'il faut pour que notre navigateur comprenne qu'il s'agit d'une redirection. Cet objet prend en argument de son constructeur l'URL vers laquelle rediriger, URL que vous générez grâce au routeur bien entendu.

Voyez par vous-même ce que cela donne comme code :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse; // Nouveau use

class AdvertController extends Controller
{
  public function view($id)
  {
    $url = $this->generateUrl('oc_advert_index');
    
    return new RedirectResponse($url);
  }
}

Essayez d'aller à l'adresse /advert/view/5 et vous serez redirigés vers l'accueil !

À l'image de la méthode render, il existe également une méthode raccourcie pour faire une redirection depuis un contrôleur, il s'agit de la méthode redirect qui prend en argument l'URL. L'avantage est que vous n'avez pas à rajouter le use RedirectResponse en début de fichier, la méthode crée la réponse elle-même :

<?php

public function view($id)
{
  $url = $this->generateUrl('oc_advert_index');
  
  return $this->redirect($url);
}

Vous trouvez ça encore trop long ? Allez, je vous le raccourci un peu plus (et on est bien d'accord que cela fait strictement la même chose !) :

<?php

public function viewAction($id)
{
  return $this->redirectToRoute('oc_advert_index');
}

La méthode  redirectToRoute  prend directement en argument la route vers laquelle rediriger, et non l'URL, très pratique !

La redirection s'est bien effectuée, mais cela a été trop vite ? Vous auriez aimé savoir ce qu'il se passe sur la page avant la redirection ?

Symfony a la réponse ! Je vous invite dès maintenant à modifier la valeur du paramètre intercept_redirects  à true dans le fichier config/packages/dev/web_profiler.yaml . Ensuite, retournez  à l'adresse /advert/view/5 et vous obtiendrez la figure suivante.

Symfony a intercepté notre redirection et affiche une page avec la toolbar
Symfony a intercepté notre redirection et affiche une page avec la barre d'outil

Symfony n'envoie pas l'entête de redirection au navigateur, mais à la place affiche une page avec... la barre d'outil ! Cela vous permet d'avoir plein d'informations sur la page qui vient de s'exécuter. Dans notre cas, ici, cela a peu d'intérêt, mais imaginez le cas où vous exécutez des requêtes SQL avant de faire la redirection, très pratique pour déboguer !

Et bien entendu, ce mécanisme n'existe qu'en mode "dev", pour ne pas venir déranger le mode "prod".

Changer le Content-Type de la réponse

Lorsque vous retournez autre chose que du HTML, il faut que vous changiez l'en-tête Content-Typede la réponse. Ce dernier permet au navigateur qui recevra votre réponse de savoir à quoi s'attendre dans le contenu. Prenons l'exemple suivant : vous recevez une requête AJAX et souhaitez retourner un tableau en JSON :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends AbstractController
{
  public function view($id)
  {
    // Créons nous-mêmes la réponse en JSON, grâce à la fonction json_encode()
    $response = new Response(json_encode(['id' => $id]));

    // Ici, nous définissons le Content-Type pour dire au navigateur
    // que l'on renvoie du JSON et non du HTML
    $response->headers->set('Content-Type', 'application/json');

    return $response;
  }
}

Testez le rendu en allant sur /advert/view/5.

<?php

use Symfony\Component\HttpFoundation\JsonResponse;

// ...

public function view($id)
{
  return new JsonResponse(['id' => $id]);
}

Manipuler la session

Une des actions classiques d'un contrôleur, c'est de manipuler la session. Définir, récupérer des variables de session, etc. sont des choses à savoir.

Dans Symfony, il existe un objet Session qui permet de gérer la session, il se récupère comme l'objet Twig, en argument de la méthode. Depuis cet objet, vous disposez des méthodes get() et set() pour récupérer et définir des variables de session :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface; // Nouveau use

class AdvertController extends AbstractController
{
  // On injecte la session avec SessionInterface
  public function viewAction($id, SessionInterface $session)
  {
    // On récupère le contenu de la variable userId
    $userId = $session->get('userId');

    // On définit une nouvelle valeur pour cette variable userId
    $session->set('userId', 91);

    // On n'oublie pas de renvoyer une réponse
    return new Response("<body>Je suis une page de test, je n'ai rien à dire</body>");
  }
}

‌La session se lance automatiquement dès que vous vous en servez. Voyez par exemple à la figure suivante ce que le Profiler me dit sur une page où je n'utilise pas la session.

On constate qu'il n'y a pas d'attribut dans la session
On constate qu'il n'y a pas d'attribut dans la session

Et voici le Profiler après que nous avons défini la variable userId en session, à la figure suivante.

Ici, on constate que l'attribut user_id est bien défini, avec comme valeur 91
Ici, on constate que l'attribut user_id est bien défini, avec comme valeur 91

Le Profiler nous donne même les informations sur la date de création de la session, etc.

Un autre outil très pratique offert par cet objet Session est ce que l'on appelle les « messages flash ». Un terme précis pour désigner en réalité une variable de session qui ne dure que le temps d'une seule page.

C'est une astuce utilisée pour les formulaires par exemple : la page qui traite le formulaire définit un message flash (« Annonce bien enregistrée » par exemple) puis redirige vers la page de visualisation de l'annonce nouvellement créée. Sur cette page, le message flash s'affiche, et est détruit de la session. Alors si l'on change de page ou qu'on l'actualise, le message flash ne sera plus présent.

Voici un exemple d'utilisation (dans la méthode add()) :

<?php
// src/Controller/AdvertController.php

public function view($id)
{
  return $this->render('Advert/view.html.twig', [
    'id' => $id,
  ]);
}
  
public function add()
{
  // Bien sûr, cette méthode devra réellement ajouter l'annonce

  // Mais faisons comme si c'était le cas
  $this->addFlash('info', 'Annonce bien enregistrée');

  // Le « flashBag » est ce qui contient les messages flash dans la session
  // Il peut bien sûr contenir plusieurs messages :
  $this->addFlash('info', 'Oui oui, elle est bien enregistrée !');

  // Puis on redirige vers la page de visualisation de cette annonce
  return $this->redirectToRoute('oc_advert_view', ['id' => 5]);
}

Vous constatez que la méthode add définit deux messages flash (appelés ici « info »).

L'ajout de ces messages se fait via la méthode raccourcie  $this->addFlash() , méthode qui utilise en interne l'objet Session.

La lecture de ces messages se fait dans la vue de l'action view, que j'ai modifiée comme ceci :

{# templates/Advert/view.html.twig #}

<!DOCTYPE html>
<html>
  <head>
    <title>Affichage de l'annonce {{ id }}</title>
  </head>
  <body>
    <h1>Affichage de l'annonce n°{{ id }} !</h1>

    <div>
      {# On affiche tous les messages flash dont le nom est « info » #}
      {% for message in app.flashes('info') %}
        <p>Message flash : {{ message }}</p>
      {% endfor %}
    </div>

    <p>
      Ici nous pourrons lire l'annonce ayant comme id : {{ id }}<br />
      Mais pour l'instant, nous ne savons pas encore le faire, cela viendra !
    </p>
  </body>
</html>

Essayez d'aller sur /advert/add, vous allez être redirigés sur la page d'affichage d'une annonce et pourrez voir les deux messages flash. Appuyez sur F5, et hop ! Ils ont disparu. C'est tout le fonctionnement des messages flash.

Application : le contrôleur de notre plateforme

Construction du contrôleur

Pour le moment nous manipulons principalement les annonces, nous allons donc mettre toutes nos actions dans un seul contrôleur « Advert ». Plus tard, nous pourrons éventuellement créer d'autres contrôleurs.

Malheureusement, on ne connaît pas encore tous les services indispensables à la création des pages. À ce point du cours, on ne sait pas encore réaliser de formulaire, manipuler les annonces dans la base de données, ni même créer de vrais templates.

Pour l'heure, notre contrôleur sera donc très simple. On va créer le squelette de toutes les actions que l'on a mises dans nos routes. Et le contrôleur « Advert » :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

/**
 * @Route("/advert")
 */
class AdvertController extends AbstractController
{
  /**
   * @Route("/{page}", name="oc_advert_index", requirements={"page" = "\d+"}, defaults={"page" = 1})
   */
  public function index($page)
  {
    // On ne sait pas combien de pages il y a
    // Mais on sait qu'une page doit être supérieure ou égale à 1
    if ($page < 1) {
      // On déclenche une exception NotFoundHttpException, cela va afficher
      // une page d'erreur 404 (qu'on pourra personnaliser plus tard d'ailleurs)
      throw $this->createNotFoundException('Page "'.$page.'" inexistante.');
    }

    // Ici, on récupérera la liste des annonces, puis on la passera au template

    // Mais pour l'instant, on ne fait qu'appeler le template
    return $this->render('Advert/index.html.twig');
  }

  /**
   * @Route("/view/{id}", name="oc_advert_view", requirements={"id" = "\d+"})
   */
  public function view($id)
  {
    // Ici, on récupérera l'annonce correspondante à l'id $id

    return $this->render('Advert/view.html.twig', [
        'id' => $id,
    ]);
  }

  /**
   * @Route("/add", name="oc_advert_add")
   */
  public function add(Request $request)
  {
    // La gestion d'un formulaire est particulière, mais l'idée est la suivante :

    // Si la requête est en POST, c'est que le visiteur a soumis le formulaire
    if ($request->isMethod('POST')) {
      // Ici, on s'occupera de la création et de la gestion du formulaire

      $this->addFlash('notice', 'Annonce bien enregistrée.');

      // Puis on redirige vers la page de visualisation de cettte annonce
      return $this->redirectToRoute('oc_advert_view', ['id' => 5]);
    }

    // Si on n'est pas en POST, alors on affiche le formulaire
    return $this->render('Advert/add.html.twig');
  }

  /**
   * @Route("/edit/{id}", name="oc_advert_edit", requirements={"id" = "\d+"})
   */
  public function edit($id, Request $request)
  {
    // Ici, on récupérera l'annonce correspondante à $id

    // Même mécanisme que pour l'ajout
    if ($request->isMethod('POST')) {
      $this->addFlash('notice', 'Annonce bien modifiée.');

      return $this->redirectToRoute('oc_advert_view', ['id' => 5]);
    }

    return $this->render('Advert/edit.html.twig');
  }

  /**
   * @Route("/delete/{id}", name="oc_advert_delete", requirements={"id" = "\d+"})
   */
  public function delete($id)
  {
    // Ici, on récupérera l'annonce correspondant à $id

    // Ici, on gérera la suppression de l'annonce en question

    return $this->render('Advert/delete.html.twig');
  }
}

À retenir

L'erreur 404

Je vous ai donné un exemple qui vous montre comment déclencher une erreur 404. C'est quelque chose que l'on fera souvent, par exemple dès qu'une annonce n'existera pas, qu'un argument ne sera pas bon (page = 0), etc. Lorsque l'on déclenche cette exception, le noyau l'attrape et génère une belle page d'erreur 404. Vous pouvez aller voir l'annexe « Comment personnaliser ses pages d'erreur ».

La définition des méthodes

Nos méthodes vont être appelées par le noyau : elles doivent donc se trouver dans le scope « public ». Vous pouvez bien entendu rajouter d'autres méthodes, par exemple pour exécuter une fonction que vous réutiliserez dans deux actions différentes.

Testons-le

Naturellement, seules les actions index et view vont fonctionner, car nous n'avons pas créé les templates associés pour les autres actions (ce sera fait dans le prochain chapitre). Cependant, nous pouvons voir le type d'erreur que Symfony nous génère dans ce cas (je vous invite à tester !).

Allez sur la page de suppression d'une annonce, à l'adresse /advert/delete/5. Vous constatez que l'erreur est très explicite et nous indique directement ce qui ne va pas : le template est introuvable. La barre d'outil nous indique que la route sélectionnée est la bonne,  oc_advert_delete .

On peut également tester notre erreur 404 générée manuellement lorsque le paramètre page est à 0. Allez sur /advert/0, et admirez notre erreur. Regardez entre autres la barre d'outil (voir figure suivante).

La page n'existe pas, une erreur 404 est renvoyée
La page n'existe pas, une erreur 404 est renvoyée

Très pratique pour vérifier que tout est comme on l'attend ! Vous pouvez également voir quelle est la ligne exacte qui a généré l'exception.

Pour conclure

Créer un contrôleur à ce stade du cours n'est pas évident, car vous ne connaissez et ne maîtrisez pas encore tous les services nécessaires. Seulement, vous avez pu comprendre son rôle et voir un exemple concret.

Rassurez-vous, dans la partie 4 du cours, on apprendra tout le nécessaire pour construire l'intérieur de nos contrôleurs. ;) En attendant, rendez-vous au prochain chapitre pour en apprendre plus sur les templates.

Pour plus d'informations concernant les contrôleurs, n'hésitez pas à lire la documentation officielle.

En résumé

  • Le rôle du contrôleur est de retourner un objet Response : ceci est obligatoire !

  • Le contrôleur construit la réponse en fonction des données qu'il a en entrée : paramètres de route et objet Request.

  • Le contrôleur se sert de tout ce dont il a besoin pour construire la réponse : la base de données, les templates, les différents services, etc.

  • Le code du cours tel qu'il doit être à ce stade est disponible sur la branche iteration-5 du dépot Github.

Example of certificate of achievement
Example of certificate of achievement