• 30 heures
  • Facile

Ce cours est visible gratuitement en ligne.

Ce cours est en vidéo.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 04/09/2017

Les contrôleurs avec Symfony2

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

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, les modèles et appeler la vue. 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, Symfony2 s'est inspiré des concepts du protocole HTTP. Il existe dans Symfony2 les classesRequest et Response. Retourner une réponse signifie donc tout simplement : instancier un objetResponse, disons$response, et faire unreturn $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/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  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. 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. Vous pouvez voir le résultat dans la figure suivante.

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

Vous voyez donc tous les entêtes de la requête, qui nous permettrons de construire la réponse la plus adaptée. Et dans les entêtes de la réponse ici, vous avez ceux par défaut que Symfony inclut. 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 objetsRequestetResponsequi 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_platform_view :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_view:
    path:      /advert/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:view }
    requirements:
        id: \d+

Ici, le paramètre{id}de la requête est récupéré par la route, qui va le transformer en argument$idpour le contrôleur. On a déjà fait la méthode correspondante dans le contrôleur, la voici pour rappel :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  // …

  public function viewAction($id)
  {
    return new Response("Affichage de l'annonce d'id : ".$id);
  }
}

Voici 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/platform/advert/5?tag=developer, il nous faut bien un moyen pour récupérer ce paramètretag! C'est ici qu'intervient l'objetRequest.

Pour récupérer la requête depuis un contrôleur, vous devez réaliser une petite pirouette : il faut ajouter un argument à votre méthode avec le type Request comme ceci :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request; // N'oubliez pas ce use !
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
    public function viewAction($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é avecRequest . 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

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  // …

  // On injecte la requête dans les arguments de la méthode
  public function viewAction($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 :/platform/advert/9?tag=developer.

Nous avons utilisé$request->querypour 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 faire $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 faites$request->query->get('sdf')alors que le paramètresdfn'est pas défini dans l'URL, cela vous retournera une chaîne vide, et non une erreur.

Les autres méthodes de l'objetRequest

Heureusement, l'objetRequestne 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'objetRequest, 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 objetResponse

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) :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  // On modifie viewAction, car elle existe déjà
  public function viewAction($id)
  {
    // 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 esthttp://localhost/Symfony/web/app_dev.php/platform/advert/5si vous avez gardé les mêmes routes depuis le début.

Je ne vous le cache pas : nous n'utiliserons jamais cette longue méthode ! 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, le service templating que nous avons déjà utilisé dispose d'un raccourci : la méthoderenderResponse(). Elle prend en paramètres le nom du template et ses variables, puis s'occupe de tout : créer la réponse, y passer le contenu du template, et retourner la réponse. La voici en action :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    // On utilise le raccourci : il crée un objet Response
    // Et lui donne comme contenu le contenu du template
    return $this->get('templating')->renderResponse(
      'OCPlatformBundle:Advert:view.html.twig',
      array('id'  => $id)
    );
  }
}

Et voilà, en une seule ligne, c'est bouclé ! Et nous pouvons même aller encore plus loin, le contrôleur lui-même dispose d'un raccourci pour utiliser cette méthode renderResponse, il s'agit de la méthoderender qui s'utilise exactement de la même façon, la voici en action :

<?php

  public function viewAction($id)
  {
    return $this->render(
      'OCPlatformBundle:Advert:view.html.twig',
      array('id'  => $id)
    );
  }

C'est comme cela que nous générerons la plupart de nos réponses. Finalement, l'objetResponseest 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 :

{# src/OC/PlatformBundle/Resources/view/Advert/view.html.twig #}

<!DOCTYPE html>
<html>
  <head>
    <title>Affichage de l'annonce {{ id }}</title>
  </head>
  <body>
    <h1>Hello Annonce n°{{ id }} !</h1>
  </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 ce 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/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse; // N'oubliez pas ce use
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    $url = $this->get('router')->generate('oc_platform_home');
    
    return new RedirectResponse($url);
  }
}

Essayez d'aller à l'adresse /platform/advert/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 leuse RedirectResponse en début de fichier :

<?php

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

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

<?php

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

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 fichierapp/config/config_dev.yml. Ensuite, retournez  à l'adresse /platform/advert/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 toolbar

Symfony n'envoie pas l'entête de redirection au navigateur, mais à la place affiche une page avec... la toolbar ! Ce qui 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ébuguer !

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

Changer leContent-typede la réponse

Lorsque vous retournez autre chose que du HTML, il faut que vous changiez leContent-typede la réponse. CeContent-typepermet 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/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    // Créons nous-mêmes la réponse en JSON, grâce à la fonction json_encode()
    $response = new Response(json_encode(array('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 /platform/advert/5.

<?php

use Symfony\Component\HttpFoundation\JsonResponse;

// ...

public function viewAction($id)
{
  return new JsonResponse(array('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 depuis la requête. Depuis cet objet, vous disposez des méthodesget()etset() pour récupérer et définir des variables de session :

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

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  public function viewAction($id, Request $request)
  {
    // Récupération de la session
    $session = $request->getSession();
    
    // On récupère le contenu de la variable user_id
    $userId = $session->get('user_id');

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

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

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 variableuser_iden 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 object 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éthodeaddAction()) :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

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

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    return $this->render('OCPlatformBundle:Advert:view.html.twig', array(
      'id' => $id
    ));
  }
    
  // Ajoutez cette méthode :
  public function addAction(Request $request)
  {
    $session = $request->getSession();
    
    // Bien sûr, cette méthode devra réellement ajouter l'annonce
    
    // Mais faisons comme si c'était le cas
    $session->getFlashBag()->add('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 :
    $session->getFlashBag()->add('info', 'Oui oui, elle est bien enregistrée !');

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

Vous pouvez voir que la méthodeaddActiondéfinit deux messages flash (appelés ici « info »). La lecture de ces messages se fait dans la vue de l'actionviewAction, que j'ai modifiée comme ceci :

{# src/OC/PlatformBundle/Resources/view/Advert/view.html.twig #}

<!DOCTYPE html>
<html>
  <head>
    <title>Bienvenue sur ma première page avec OpenClassrooms !</title>
  </head>
  <body>
    <h1>Affichage d'une annonce</h1>

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

    <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 /platform/add, vous allez être redirigés sur la page d'affichage d'une annonce et voir le message flash. Faites F5, et hop ! Il a disparu.

Application : le contrôleur de notre plateforme

Construction du contrôleur

Notre plateforme est un bundle plutôt simple. Pour le moment nous manipulons principalement les annonces, on va 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. Je vous remets sous les yeux nos routes, et on enchaîne sur le contrôleur :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_home:
    path:      /{page}
    defaults:  { _controller: OCPlatformBundle:Advert:index, page: 1 }
    requirements:
        page: \d*

oc_platform_view:
    path:      /advert/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:view }
    requirements:
        id: \d+

oc_platform_add:
    path:      /add
    defaults:  { _controller: OCPlatformBundle:Advert:add }

oc_platform_edit:
    path:      /edit/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:edit }
    requirements:
        id: \d+

oc_platform_delete:
    path:      /delete/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:delete }
    requirements:
        id: \d+

Et le contrôleur « Advert » :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class AdvertController extends Controller
{
  public function indexAction($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 new NotFoundHttpException('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('OCPlatformBundle:Advert:index.html.twig');
  }

  public function viewAction($id)
  {
    // Ici, on récupérera l'annonce correspondante à l'id $id

    return $this->render('OCPlatformBundle:Advert:view.html.twig', array(
      'id' => $id
    ));
  }

  public function addAction(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

      $request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');

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

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

  public function editAction($id, Request $request)
  {
    // Ici, on récupérera l'annonce correspondante à $id

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

      return $this->redirectToRoute('oc_platform_view', array('id' => 5));
    }

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

  public function deleteAction($id)
  {
    // Ici, on récupérera l'annonce correspondant à $id

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

    return $this->render('OCPlatformBundle: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 respecter le nom et les arguments que nous avons définis dans nos routes et 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. Dans ce cas, vous ne devez pas les suffixer de « Action » (afin de ne pas confondre).

Testons-le

Naturellement, seules les actionsindexetvoirvont fonctionner, car nous n'avons pas créé les templates associés (ce sera fait dans le prochain chapitre). Cependant, nous pouvons voir le type d'erreur que Symfony2 nous génère dans ce cas.

Allez sur la page de suppression d'une annonce, à l'adresse http://localhost/Symfony/web/app_dev.php/platform/delete/5. Vous pouvez voir que l'erreur est très explicite et nous permet de voir directement ce qui ne va pas. On a même les logs en dessous de l'erreur : on peut voir tout ce qui a fonctionné avant que l'erreur ne se déclenche. Notez par exemple le log n°1 :

INFO - Matched route "oc_platform_delete" (parameters: "_controller": "OC\PlatformBundle\Controller\AdvertController::deleteAction", "id": "5", "_route": "oc_platform_delete") 

On voit que c'est bien la bonne route qui est utilisée, super ! On voit aussi que le paramètreidest bien défini à 5 : re-super !

On peut également tester notre erreur 404 générée manuellement lorsque ce paramètrepageest à 0. Allez sur http://localhost/Symfony/web/app_dev.php/platform/0, et admirez notre erreur. Regardez entre autres la toolbar (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 objetResponse: ceci est obligatoire !

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

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

Exemple de certificat de réussite
Exemple de certificat de réussite