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
- Manipuler l'objet Request
- Manipuler l'objet Response
- Les différents services
- Application : le contrôleur de notre blog
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 : 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 une classe 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éer 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 ! » :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { public function indexAction() { return new Response("Hello World !"); } } |
Et voilà, votre contrôleur remplit parfaitement son rôle !
Bien sûr, 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
etResponse
qui vont vous permettre de construire une réponse en fonction de la requête ; - Les services 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'un article à 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 route sdzblog_voir
:
1 2 3 4 5 6 7 | # src/Sdz/BlogBundle/Resources/config/routing.yml sdzblog_voir: path: /article/{id} defaults: { _controller: SdzBlogBundle:Blog:voir } 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 $id
pour le contrôleur. On a déjà fait la méthode correspondante dans le contrôleur, la voici pour rappel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { // … public function voirAction($id) { return new Response("Affichage de l'article 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 /blog/article/5?tag=vacances
, il nous faut bien un moyen pour récupérer ce paramètre tag
! C'est ici qu'intervient l'objet Request
. Tout d'abord, voici comment récupérer la requête depuis un contrôleur :
1 2 | <?php $request = $this->getRequest(); |
Voilà, c'est aussi simple que cela ! Maintenant que nous avons notre requête, récupérons nos paramètres :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { // … public function voirAction($id) { // On récupère la requête $request = $this->getRequest(); // On récupère notre paramètre tag $tag = $request->query->get('tag'); return new Response("Affichage de l'article d'id : ".$id.", avec le tag : ".$tag); } } |
Et vous n'avez plus qu'à tester le résultat : /blog/article/9?tag=vacances
.
Nous avons utilisé <?php $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 Symfony2 |
Méthode traditionnelle |
Exemple |
---|---|---|---|
Variables d'URL |
|
\$_GET |
|
Variables de formulaire |
|
\$_POST |
|
Variables de cookie |
|
\$_COOKIE |
|
Variables de serveur |
|
\$_SERVER |
|
Variables d'entête |
|
\$SERVER['HTTP*'] |
|
Paramètres de route |
|
n/a |
|
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è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 <?php $request->getMethod() ?>
:
1 2 3 4 5 | <?php if( $request->getMethod() == '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 !
1 2 3 4 5 | <?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 Symfony2. 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 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) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { // On modifie voirAction, car elle existe déjà public function voirAction($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 // Rappelez-vous, 404 correspond à « page introuvable » $response->setStatusCode(404); // On retourne la réponse return $response; } } |
N'hésitez pas à tester cette page, l'URL est http://localhost/Symfony/web/app_dev.php/blog/article/5
si 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, dans un template. Heureusement pour nous, le contrôleur dispose d'un raccourci : la méthode <?php $this->render()
. 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; // Nous n'avons plus besoin du use pour l'objet Response // use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { public function voirAction($id) { // On utilise le raccourci : il crée un objet Response // Et lui donne comme contenu le contenu du template return $this->render('SdzBlogBundle:Blog:voir.html.twig', array( 'id' => $id, )); } } |
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.
N'oubliez pas de créer la vue associée bien entendu :
1 2 3 4 5 6 7 8 9 10 11 | {# src/Sdz/BlogBundle/Resources/view/Blog/voir.html.twig #} <!DOCTYPE html> <html> <head> <title>Lecture de l'article {{ id }}</title> </head> <body> <h1>Hello Article n°{{ id }} !</h1> </body> </html> |
Si vous ne deviez retenir qu'une seule chose de cette section, c'est bien cette méthode <?php $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 faire cela, il existe également un raccourci du contrôleur : la méthode <?php $this->redirect()
. Elle prend en paramètre l'URL vers laquelle vous souhaitez faire la redirection et s'occupe de créer une réponse, puis d'y définir un header qui contiendra votre URL. En action, cela donne le code suivant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class BlogController extends Controller { public function voirAction($id) { // On utilise la méthode « generateUrl() » pour obtenir l'URL de la liste des articles à la page 2 // Par exemple return $this->redirect( $this->generateUrl('sdzblog_accueil', array('page' => 2)) ); } } |
Essayez d'aller à l'adresse http://localhost/Symfony/web/app_dev.php/blog/article/5
et vous serez redirigés vers l'accueil !
Changer le Content-type de la réponse
Lorsque vous retournez autre chose que du HTML, il faut que vous changiez le Content-type
de la réponse. Ce Content-type
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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { public function voirAction($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 que l'on renvoie du JSON et non du HTML $response->headers->set('Content-Type', 'application/json'); return $response; // Nous n'avons pas utilisé notre template ici, car il n'y en a pas vraiment besoin } } |
Testez le rendu en allant sur http://localhost/Symfony/web/app_dev.php/blog/article/5
.
Les différents services
Qu'est-ce qu'un service ?
Je vous en ai déjà brièvement parlé : un service est un script qui remplit un rôle précis et que l'on peut utiliser depuis notre contrôleur.
Imaginez par exemple un service qui a pour but d'envoyer des e-mails. Depuis notre contrôleur, on appelle ce service, on lui donne les informations nécessaires (contenu de l'e-mail, destinataire, etc.), puis on lui dit d'envoyer l'e-mail. Ainsi, toute la logique « création et envoi d'e-mail » se trouve dans ce service et non dans notre contrôleur. Cela nous permet de réutiliser ce service très facilement ! En effet, si vous codez en dur l'envoi d'e-mail dans un contrôleur A et que, plus tard, vous avez envie d'envoyer un autre e-mail depuis un contrôleur B, comment réutiliser ce que vous avez déjà fait ? C'est impossible et c'est exactement pour cela que les services existent.
Il existe un chapitre sur les services plus loin dans ce tutoriel. N'allez pas le lire maintenant, car il demande des notions que vous n'avez pas encore. Patience, sachez juste que c'est un point incontournable de Symfony2 et que nous le traiterons bien plus en détail par la suite.
Accéder aux services
Pour accéder aux services depuis votre contrôleur, il faut utiliser la méthode <?php $this->get()
du contrôleur. Par exemple, le service pour envoyer des e-mails se nomme justement « mailer ». Pour employer ce service, nous faisons donc :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { public function voirAction($id) { // Récupération du service $mailer = $this->get('mailer'); // Création de l'e-mail : le service mailer utilise SwiftMailer, donc nous créons une instance de Swift_Message $message = \Swift_Message::newInstance() ->setSubject('Hello zéro !') ->setFrom('tutorial@symfony2.com') ->setTo('votre@email.com') ->setBody('Coucou, voici un email que vous venez de recevoir !'); // Retour au service mailer, nous utilisons sa méthode « send() » pour envoyer notre $message $mailer->send($message); // N'oublions pas de retourner une réponse, par exemple une page qui afficherait « L'e-mail a bien été envoyé » return new Response('Email bien envoyé'); } } |
Pour que l'envoi d'e-mail fonctionne, n'oubliez pas de configurer vos paramètres si ce n'est pas déjà fait. Ouvrez le fichier app/config/parameters.yml
pour modifier les paramètres mailer_*
. Si vous voulez utiliser votre compte Gmail :
1 2 3 4 5 6 | # app/config/parameters.yml mailer_transport: gmail mailer_host: mailer_user: vous@gmail.com mailer_password: mdp |
Et si vous voulez utiliser un serveur SMTP classique :
1 2 3 4 5 6 | # app/config/parameters.yml mailer_transport: smtp mailer_host: smtp.votre-serveur.fr mailer_user: identifiant mailer_password: mdp |
Chargez la page /blog/article/5
, et allez lire votre e-mail !
Retenez donc la méthode <?php $this->get('nom_du_service')
!
Brève liste des services
Maintenant que vous savez récupérer des services, encore faut-il connaître leur nom ! Et savoir les utiliser ! Ci-après est dressée une courte liste de quelques services utiles.
Templating
Templating est un service qui vous permet de gérer vos templates (vos vues, vous l'aurez compris). En fait, vous avez déjà utilisé ce service… via le raccourci <?php $this->render
! Voici la version longue d'un <?php $this->render('MonTemplate')
:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php // … public function voirAction($id) { // Récupération du service $templating = $this->get('templating'); // On récupère le contenu de notre template $contenu = $templating->render('SdzBlogBundle:Blog:voir.html.twig'); // On crée une réponse avec ce contenu et on la retourne return new Response($contenu); } |
Le service Templating est utile, par exemple, pour notre e-mail de tout à l'heure. Nous avons écrit le contenu de l'e-mail en dur, ce qui n'est pas bien, évidemment. Nous devrions avoir un template pour cela. Et pour en récupérer le contenu, nous utilisons <?php $templating->render()
.
Une autre fonction de ce service qui peut servir, c'est <?php $templating->exists('SdzBlogBundle:Blog:inexistant')
qui permet de vérifier si « SdzBlogBundle:Blog:inexistant » existe ou non.
Request
Eh oui, encore elle. C'est également un service ! Tout à l'heure on l'a récupéré via $this->getRequest()
, mais on aurait également pu la récupérer de cette façon : <?php $this->get('request')
. En fait, la première méthode n'est qu'un raccourci vers la deuxième.
Session
Les outils de session sont également intégrés dans un service. Vous pouvez le récupérer via <?php $this->get('session')
. Pour définir et récupérer des variables en session, il faut utiliser les méthodes get()
et set()
, tout simplement :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { public function voirAction($id) { // Récupération du service $session = $this->get('session'); // On récupère le contenu de la variable user_id $user_id = $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('Désolé je suis une page de test, je n\'ai rien à dire'); } } |
Pour connaître les variables de la session courante, allez dans le Profiler (la barre d'outils en bas), rubrique Request
, puis descendez tout en bas au paragraphe « Session Attributes ». Très utile pour savoir si vous avez bien les variables de session que vous attendez.
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.
Et voici le Profiler après que nous avons défini la variable user_id
en session, à la figure suivante.
Le Profiler nous donne même les informations sur la date de création de la session, etc.
Un autre outil très pratique du service de 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 (« Article bien enregistré » par exemple) puis redirige vers la page de visualisation de l'article nouvellement créé. 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 ajouterAction()
) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class BlogController extends Controller { public function voirAction($id) { return $this->render('SdzBlogBundle:Blog:voir.html.twig', array( 'id' => $id )); } // Ajoutez cette méthode ajouterAction : public function ajouterAction() { // Bien sûr, cette méthode devra réellement ajouter l'article // Mais faisons comme si c'était le cas $this->get('session')->getFlashBag()->add('info', 'Article bien enregistré'); // Le « flashBag » est ce qui contient les messages flash dans la session // Il peut bien sûr contenir plusieurs messages : $this->get('session')->getFlashBag()->add('info', 'Oui oui, il est bien enregistré !'); // Puis on redirige vers la page de visualisation de cet article return $this->redirect( $this->generateUrl('sdzblog_voir', array('id' => 5)) ); } } |
Vous pouvez voir que la méthode ajouterAction
définit deux messages flash (appelés ici « info »). La lecture de ces messages se fait dans la vue de l'action voirAction
, que j'ai modifiée comme ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | {# src/Sdz/BlogBundle/Resources/views/Blog/voir.html.twig #} <!DOCTYPE html> <html> <head> <title>Bienvenue sur ma première page avec le Site du Zéro !</title> </head> <body> <h1>Lecture d'un article</h1> <p> {# On affiche tous les messages flash dont le nom est « info » #} {% for message in app.session.flashbag.get('info') %} <p>{{ message }}</p> {% endfor %} </p> <p> Ici nous pourrons lire l'article ayant comme id : {{ id }}<br /> Mais pour l'instant, nous ne savons pas encore le faire, cela viendra ! </p> </body> </html> |
La variable Twig {{ app }}
est une variable globale, disponible partout dans vos vues. Elle contient quelques variables utiles, nous le verrons, dont le service « session » que nous venons d'utiliser via {{ app.session }}
.
Essayez d'aller sur http://localhost/Symfony/web/app_dev.php/blog/ajouter
, vous allez être redirigés et voir le message flash. Faites F5, et hop ! il a disparu.
Sachez également que le service « session » est aussi accessible depuis le service « request ». Ainsi, depuis un contrôleur vous pouvez faire :
1 2 | <?php $session = $this->getRequest()->getSession(); |
Les autres… et les nôtres !
Il existe évidemment bien d'autres services : nous les rencontrerons au fur et à mesure dans ce cours.
Mais il existera surtout nos propres services ! En effet, la plupart des outils que nous allons créer (un formulaire, un gestionnaire d'utilisateurs personnalisé, etc.) devront être utilisés plusieurs fois. Quoi de mieux, dans ce cas, que de les définir en tant que services ? Nous verrons cela dans la partie 4, mais sachez qu'après une petite étape de mise en place (configuration, quelques conventions), les services sont vraiment très pratiques !
Application : le contrôleur de notre blog
Construction du contrôleur
Notre blog est un bundle plutôt simple. On va mettre toutes nos actions dans un seul contrôleur « Blog ». Plus tard, nous pourrons éventuellement créer un contrôleur « Tag » pour manipuler les tags.
Malheureusement, on ne connaît pas encore tous les services indispensables. À ce point du cours, on ne sait pas réaliser de formulaire, manipuler les articles 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 la base 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # src/Sdz/BlogBundle/Resources/config/routing.yml sdzblog_accueil: path: /{page} defaults: { _controller: SdzBlogBundle:Blog:index, page: 1 } requirements: page: \d* sdzblog_voir: path: /article/{id} defaults: { _controller: SdzBlogBundle:Blog:voir } requirements: id: \d+ sdzblog_ajouter: path: /ajouter defaults: { _controller: SdzBlogBundle:Blog:ajouter } sdzblog_modifier: path: /modifier/{id} defaults: { _controller: SdzBlogBundle:Blog:modifier } requirements: id: \d+ sdzblog_supprimer: path: /supprimer/{id} defaults: { _controller: SdzBlogBundle:Blog:supprimer } requirements: id: \d+ |
Et le contrôleur « Blog » :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <?php // src/Sdz/BlogBundle/Controller/BlogController.php namespace Sdz\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Httpfoundation\Response; class BlogController 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 la page d'erreur 404 (on pourra personnaliser cette page plus tard d'ailleurs) throw $this->createNotFoundException('Page inexistante (page = '.$page.')'); } // Ici, on récupérera la liste des articles, puis on la passera au template // Mais pour l'instant, on ne fait qu'appeler le template return $this->render('SdzBlogBundle:Blog:index.html.twig'); } public function voirAction($id) { // Ici, on récupérera l'article correspondant à l'id $id return $this->render('SdzBlogBundle:Blog:voir.html.twig', array( 'id' => $id )); } public function ajouterAction() { // La gestion d'un formulaire est particulière, mais l'idée est la suivante : if( $this->get('request')->getMethod() == 'POST' ) { // Ici, on s'occupera de la création et de la gestion du formulaire $this->get('session')->getFlashBag()->add('notice', 'Article bien enregistré'); // Puis on redirige vers la page de visualisation de cet article return $this->redirect( $this->generateUrl('sdzblog_voir', array('id' => 5)) ); } // Si on n'est pas en POST, alors on affiche le formulaire return $this->render('SdzBlogBundle:Blog:ajouter.html.twig'); } public function modifierAction($id) { // Ici, on récupérera l'article correspondant à $id // Ici, on s'occupera de la création et de la gestion du formulaire return $this->render('SdzBlogBundle:Blog:modifier.html.twig'); } public function supprimerAction($id) { // Ici, on récupérera l'article correspondant à $id // Ici, on gérera la suppression de l'article en question return $this->render('SdzBlogBundle:Blog:supprimer.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'un article 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 actions index
et voir
vont 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. Allez sur la page de suppression d'un article, à l'adresse http://localhost/Symfony/web/app_dev.php/blog/supprimer/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°4 :
1 | Matched route "sdzblog_supprimer" (parameters: "_controller": "Sdz\BlogBundle\Controller\BlogController::supprimerAction", "id": "5", "_route": "sdzblog_supprimer")
|
On voit que c'est bien la bonne route qui est utilisée, super ! On voit aussi que le paramètre id
est bien défini à 5 : re-super !
On peut également tester notre erreur 404 générée manuellement lorsque ce paramètre page
est à 0. Allez sur http://localhost/Symfony/web/app_dev.php/blog/0
, et admirez notre erreur. Regardez entre autres la toolbar (voir figure suivante).
Très pratique pour vérifier que tout est comme on l'attend !
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 tutoriel, 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ètre 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 vues, les différents services, etc.