Aller au menu - Aller au contenu

Icône Les contrôleurs avec Symfony2

Avatar
Mise à jour : 02/05/2012
Difficulté : Intermédiaire Intermédiaire Durée d'étude : 1 heure Creative Commons BY-NC-SA
20 752 visites depuis 7 jours, dont 674 sur ce chapitre classé 17/786
Ah, le contrôleur ! Notre ami !

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, 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 le plus ultime : retourner une réponse !

Bonne lecture !
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

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 langage HTTP. Il existe dans Symfony2 une classe Response. Retourner une réponse signifie donc tout simplement : instancier un objet Response, disons <?php $response et faire un <?php return $response.

Voici le contrôleur le plus simple qui soit, c'est le contrôleur que l'on a 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 ! » :

Code : PHP
 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 2 parties :
  • les objets Request et Response 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 ou bien le nom d'un membre à chercher dans la base de données, etc. 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 :
Code : Autre
1
2
3
sdzblog_voir:
    pattern:   /article/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:voir }

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 :
Code : PHP
 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.".");
    }
}

Mais afin de respecter la méthode MVC, mettons le contenu de la page dans une vue Twig. Créez donc le fichier src/Sdz/BlogBundle/Resources/views/Blog/voir.html.twig avec ce code :

Code : HTML & Django
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{# 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>
            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>

Et bien entendu, on met à jour le contrôleur pour utiliser cette vue. Cela se fait avec la méthode render() du contrôleur. Cette méthode crée un objet Response comme dans l'exemple ci-dessus, en remplissant son contenu avec le contenu de la vue que l'on vient de créer. Voici notre contrôleur mis à jour :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?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 utilise la méthode render()
        return $this->render('SdzBlogBundle:Blog:voir.html.twig', array('id' => $id));
    }
}

Vous pouvez maintenant vous amuser à consulter l'adresse http://localhost/Symfony/web/app_dev.php/blog/article/7.

Les paramètres hors routes


Vous avez vu : dans la première méthode, nous n'avons pas utilisé du tout l'objet Request. Du moins… pas explicitement ! En fait, Symfony2 s'en est bien servi, mais sans nous le dire. Mais si par exemple nous avons une URL du type /blog/article/5?tag=vacances, il nous faut bien un moyen pour récupérer ce paramètre « tag » contenu dans l'URL !

Tout d'abord, récupérons l'objet Request depuis notre contrôleur : <?php $request = $this->get('request');. Voilà, c'est aussi simple que ça. La méthode get() du contrôleur, nous en reparlerons, permet d'accéder à toute sorte de service, dont notre requête. Maintenant que nous l'avons, récupérons nos paramètres :

Code : PHP
 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
<?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->get('request');

        // On récupère notre paramètre tag.
        $tag = $request->query->get('tag');

        return $this->render('SdzBlogBundle:Blog:voir.html.twig', array(
            'id'  => $id,
            'tag' => $tag
        ));
    }
}

Nous avons utilisé <?php $request->query pour récupérer les paramètres de l'URL passés en « GET ». Mais nous aurions pu utiliser <?php $request->cookies pour les cookies, ou bien <?php $request->request pour les paramètres « POST ».

Pour faire apparaître la variable tag dans notre template, modifions-le :
Code : HTML & Django
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{# 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>
            Ici nous pourrons lire l'article ayant comme id : {{ id }}<br />
            Cet article pourrait avoir comme tag « {{ tag }} »<br />
            Mais pour l'instant, nous ne savons pas encore le faire, cela viendra !
        </p>
    </body>
</html>


Et vous n'avez plus qu'à tester le résultat bien sûr : http://localhost/Symfony/web/app_dev.p [...] ?tag=vacances

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() ?> pour cela :
Code : PHP
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 !
Code : PHP
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 : http://api.symfony.com/2.0/Symfony/Com [...] /Request.html. Vous y trouverez toutes les méthodes, même si nous en 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 coulisse 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) :
Code : PHP
 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
<?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ètre 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 :
Code : PHP
 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,
            'tag' => 'Politique'
        ));
    }
}

Et voilà, en une seule ligne, c'est bouclé ! C'est comme ça 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.

Si vous ne deviez retenir qu'une seule chose de ce paragraphe, 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é à 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 :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?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é 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 :

Code : PHP
 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 ce 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 aviez 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 nous les 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 :
Code : PHP
 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'email a bien été envoyé ».
        return new Response('Email bien envoyé');
    }
}


Retenez donc la méthode <?php $this->get('nom_du_service') !


Brève liste des services


Évidemment, vous savez récupérer un service, mais encore faut-il connaître leur nom ! Et savoir les utiliser ! Ci-dessous 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') :
Code : PHP
 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('MonTemplate') qui permet de vérifier si « MonTemplate » existe ou non.

Request


Eh oui, encore elle. C'est également un service ! C'est pour cela qu'on l'a récupéré de cette façon : <?php $this->get('request').

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 :

Code : PHP
 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 connaitre 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 ;) .


Un autre outil très pratique du service de session est ce que l'on appelle les "flash". Un terme précis pour désigner en réalité une variable de session qui ne dure que pendant 1 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 disparait. Mais si l'on change de page ou qu'on l'actualise, le message flash ne sera plus présent. Voici un exemple d'utilisation :

Code : PHP
 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
{
    public function voirAction($id)
    {
        return $this->render('SdzBlogBundle:Blog:voir.html.twig', array(
            'id'  => $id
        ));
    }
    
    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')->setFlash('info', 'Article 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 un message flash (appelé ici "info"). La lecture de ce message se fait dans la vue de l'action voirAction, que j'ai modifié comme ceci :

Code : HTML & Django
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{# 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 #}
            
            {% for key, flash in app.session.getFlashes() %}
                {{ flash }}
            {% 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 :) .

Essayez d'aller sur http://localhost/Symfony/web/app_dev.php/blog/ajouter vous allez être redirigé et voir le message flash. Faites F5 et hop, il a disparu !

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 service ? Nous verrons cela dans la partie 2, 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 un 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 :
Code : Autre
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:
    pattern:   /{page}
    defaults:  { _controller: SdzBlogBundle:Blog:index, page: 1 }
    requirements:
        page:  \d+

sdzblog_voir:
    pattern:   /article/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:voir }
    requirements:
        id: \d+

sdzblog_ajouter:
    pattern:   /ajouter
    defaults:  { _controller: SdzBlogBundle:Blog:ajouter }

sdzblog_modifier:
    pattern:   /modifier/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:modifier }
    requirements:
        id:  \d+

sdzblog_supprimer:
    pattern:   /supprimer/{id}
    defaults:  { _controller: SdzBlogBundle:Blog:supprimer }
    requirements:
        id:  \d+

Et le contrôleur Blog :
Code : PHP
 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
<?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');
    }
    
    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')->setFlash('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 à l'$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 à l'$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 ou 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 le cookbook 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éfini 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" en 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°7 : Citation
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éfinit à 5 par défaut : re-super !

On peut également tester notre erreur 404 générée manuellement lorsque ce paramètre « page » est à zéro. Allez sur http://localhost/Symfony/web/app_dev.php/blog/0, et admirez notre erreur. Regardez entre autres la toolbar, nous avons bien : « BlogController::indexAction|sdzblog_accueil|404 ». Il se lit comme cela :
  • BlogController::indexAction : c'est le contrôleur et sa méthode utilisée ;
  • sdzblog_accueil : c'est le nom de la route utilisée ;
  • 404 : c'est le code HTTP retourné. Ici, 404 correspond bien à notre « page introuvable ».
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 3 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.

Le code tel qu'il doit être à la fin de ce chapitre est ici : https://github.com/winzou/SdzBlog/tree [...] 3a2ae08e2ffe1 N'hésitez pas à y jeter un oeil ;)


Pour plus d'informations concernant les contrôleurs, n'hésitez pas à lire la documentation officielle.
Chapitre précédent Sommaire Chapitre suivant

Partager

27 commentaires pour "Les contrôleurs avec Symfony2"
Note moyenne : 3.75 / 4 (245 votes)
Pseudo Commentaire
Hors ligne xtonex # Posté le 01/03/2012 à 15:34:02
Avatar

Avis : Très bon
Flux RSS

Excellent tutoriel :)
Bravo !
 
Hors ligne ko_ok70 # Posté le 27/03/2012 à 15:56:30
@silence
Avatar

Avis : Très bon

Excellent tutoriel et excellent chapitre

Sauf pour l'exemple "Réponse et redirection"
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?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)) );
    }
}?

quand je clic sur http://localhost/Symfony/web/app_dev.php/blog/article/5(dans mon routing j'ai bien sdzblog_accueil)
j'ai tj cette réponse:
Method "Sdz\BlogBundle\Controller\BlogController::indexAction" does not exist.
500 Internal Server Error - InvalidArgumentException
merci Winzou

Mes yeux de Coleur # :D ;)
 
Hors ligne winzou # Posté le 27/03/2012 à 18:21:40
lala
Avatar

Avis : Très bon Modérateurs

Ville : Singapour
Pays : Singapour
Études : Ecole Centrale de Lyon

Salut,

On a définit la méthode indexAction() tout au début du chapitre, il ne fallait pas la supprimer ;)

Un tutoriel pour débuter avec le framework Symfony2.
Chapitre en beta-test : Déployer son site Symfony2 en production, donnez vos avis !

Je recherche toujours quelqu'un capable de faire des icônes sympas pour les chapitres du tutoriel, contactez-moi, merci !
 
Hors ligne tsubasa456 # Posté le 19/04/2012 à 17:28:35
Avatar

Avis : Très bon

Salut !

Merci pour cet excellent tuto !

J'ai une petite question sur la dernière partie de ce tutoriel (Application : le contrôleur de notre blog -> Testons-le)le lien
"http://localhost/Symfony/web/app_dev.php/supprimer/5" ne devrait pas être plûtot "http://localhost/Symfony/web/app_dev.php/blog/supprimer/5"?

Merci d'avance :)
Hors ligne winzou # Posté le 19/04/2012 à 19:56:38
lala
Avatar

Avis : Très bon Modérateurs

Ville : Singapour
Pays : Singapour
Études : Ecole Centrale de Lyon

Salut,

Si tout à fait, je viens de modifier le lien ;) Merci !

Un tutoriel pour débuter avec le framework Symfony2.
Chapitre en beta-test : Déployer son site Symfony2 en production, donnez vos avis !

Je recherche toujours quelqu'un capable de faire des icônes sympas pour les chapitres du tutoriel, contactez-moi, merci !
 

Voir tous les commentaires