Aller au menu - Aller au contenu

Icône Récupérer directement des entités Doctrine dans son contrôleur

Avatar
Mise à jour : 02/05/2012
Difficulté : Facile Facile Durée d'étude : 30 minutes Creative Commons BY-NC-SA
20 752 visites depuis 7 jours, dont 202 sur ce chapitre classé 17/786
L'objectif de cette astuce, comme de beaucoup d'autres, est de vous faire gagner du temps et des lignes de code. Sympa, non ? :)
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Théorie : pourquoi un ParamConverter ?

Récupérer des objets Doctrine avant même le contrôleur



Sur la page d'affichage d'un article de blog, par exemple, n'êtes-vous pas fatigué de toujours devoir vérifier l'existence de l'article demandé et de l'instancier vous-même ? N'avez-vous pas l'impression d'écrire toujours et encore les mêmes lignes ?
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
public function voirwAction($id)
{
	if( ! $article = $this->get('doctrine')->getEntityManager()->getRepository('Sdz\BlogBundle\Entity\Article')->find($id) )
	{
            throw new NotFoundHttpException(sprintf('L\'article id:"%s" n\'existe pas.', $id));
        }

	// votre vrai code

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

Pour enfin vous concentrer sur votre code métier, Symfony a évidemment tout prévu !

Les ParamConverters


Vous pouvez créer ou utiliser des ParamConverters qui vont agir juste après le routeur. Les ParamConverters vont, comme leur nom l'indique, convertir les paramètres de votre route au format que vous préférez.
En effet, depuis la route, vous ne pouvez pas tellement agir sur vos paramètres. Tout au plus, vous pouvez leur imposer des contraintes via une regex. Les ParamConverter pallient cette limitation en agissant après le routeur.

Un ParamConverter utile : DoctrineParamConverter


Vous l'aurez deviné, ce ParamConverter va nous convertir nos paramètres directement en Entity Doctrine !
  • L'idée : dans le contrôleur, à la place de la variable <?php $id, on souhaite récupérer directement une variable <?php $article qui correspond à l'article portant l'id <?php $id.
  • Le bonus : on veut également que, si l'article portant l'id <?php $id n'existe pas, une exception 404 soit levée. Après tout, c'est comme si l'on mettait dans la route : "requirements: Article exists" !


Un peu de théorie sur les ParamConverter


Comment fonctionne un ParamConverter ?
Ce n'est en fait qu'un simple listener qui écoute l'évènement kernel.controller. Cet évènement est déclenché lorsque le contrôleur sait quel contrôleur appeler (après le routeur, donc), mais avant d'exécuter effectivement le contrôleur. Ainsi, lors de cet évènement, le ParamConverter va lire la méthode de votre contrôleur pour trouver soit l'annotation, soit le type de variable que vous souhaitez. Fort de ces informations, il va se permettre de modifier le paramètre de la requête (il y a accès). Ainsi, depuis votre contrôleur, vous n'avez plus le paramètre original tel que défini dans la route, mais un paramètre modifié par votre ParamConverter qui s'est exécuté avant votre contrôleur.

Pratique : utilisation de DoctrineParamConverter

Utiliser DoctrineParamConverter



Ce ParamConverter fait partie du bundle Sensio\FrameworkBundle. C'est un bundle activé par défaut sous Symfony2. Vérifiez juste que vous ne l'avez pas désactivé.

Vous pouvez ensuite vous servir de DoctrineParamConverter. La façon la plus simple de s'en servir est la suivante.

1. Côté route


Votre route ne change pas, vous gardez un paramètre {id} à l'ancienne. Exemple (tiré de src/sdz/BlogBundle/Resources/config/routing.yml) :
Code : Autre
1
2
3
4
5
# src/Sdz/BlogBundle/Resources/config/routing.yml

sdzblog_voir:
    pattern:  /voir/{id}
    defaults: { _controller: SdzBlogBundle:Blog:voir }


2. Côté contrôleur


C'est dans le contrôleur que tout se joue et que la magie opère. Il vous suffit de changer la déclaration de votre action (dans src/Sdz/BlogBundle/Controller/BlogController.php).
  • Avant : Code : PHP
    1
    <?php public function voirAction($id)
    
  • Après : Code : PHP
    1
    2
    3
    4
    5
    6
    <?php
    // En haut du fichier
    use Sdz\BlogBundle\Entity\Article;
    
    // Et dans la classe
    public function voirAction( Article $article )
    


Voici le code complet du contrôleur :
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
use Sdz\BlogBundle\Entity\Article;

// ...

public function voirAction( Article $article )
{
        // Récupérons le titre de l'article.
        $article->getTitre();

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


Et voilà ! Vous pouvez maintenant utiliser directement <?php $article->getTitre() ou tout autre code utilisant <?php $article dans votre contrôleur. Pratique, n'est-ce pas ?
Voilà donc encore une astuce qui va vous permettre d'économiser des lignes de code ! Symfony2 nous aide vraiment : fini les lignes redondantes juste pour vérifier qu'un article existe. ;)
Chapitre précédent Sommaire Chapitre suivant

Partager

8 commentaires pour "Récupérer directement des entités Doctrine dans son contrôleur"
Note moyenne : 3.75 / 4 (245 votes)
Pseudo Commentaire
Hors ligne Nami Doc # Posté le 28/07/2011 à 21:59:22
Lamaer taler dansk

Bah c'est surtout qu'il faut explicitement le préciser, avec l'annotation @ParamConverter, i.e. @ParamConverter("article", class="SdzBlogBundle:article")

Je ne sais pas si ça se fait "magiquement" via la reflection maintenant ...

La flemme conquerra le monde !
Secret (cliquez pour afficher)
Image utilisateur
 
Hors ligne winzou # Posté le 29/07/2011 à 04:03:18
lala
Avatar

Avis : Très bon Modérateurs

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

Citation : Nami Doc
Bah c'est surtout qu'il faut explicitement le préciser, avec l'annotation @ParamConverter, i.e. @ParamConverter("article", class="SdzBlogBundle:article")

Je ne sais pas si ça se fait "magiquement" via la reflection maintenant ...

Non pas besoin de le préciser. Regarde mon exemple, le seul truc qui change c'est la définition de la méthode du controleur, je n'ai rajouté aucune annotation.

C'est pour ca qu'on peut un peu parler de magie :p

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 Aerhus # Posté le 29/07/2011 à 21:52:55
Ca pandouille !
Avatar

Avis : Très bon

Ville : Seraincourt
Pays : France métropolitaine

Juste une question, qu'est-ce que ça renvoie si l'article n'est pas trouvé ? Une simple erreur 404 ? Dans ce cas c'est un poil moins personnalisable mais bon c'est pratique dans bien des cas tout de même. :)
 
Hors ligne winzou # Posté le 30/07/2011 à 04:42:01
lala
Avatar

Avis : Très bon Modérateurs

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

Exact, une simple 404 un peu moins personnalisable. Mais à mon avis tu peux t'en sortir en sachant que ta 404 vient de telle page, je vais me pencher la dessus pour voir ce qu'on peut faire c'est sur ma todo.

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 drooss # Posté le 29/08/2011 à 13:09:57

Bonjour et merci pour ces turiels Symfony2. J'ai une petite question concernant le ParamConvert.
Si le pattern de la route est view/{id} et que l'on récupère dans le contrôleur avec (Article $article), comment fait-on s'il y a plusieurs paramètres ?

Puisque j'ai vu dans le tuto sur les routes :"Notez que l'ordre des arguments dans la définition de la méthode voirSlugAction() n'a pas d'importance. La route fait la correspondance à partir du nom des variables utilisées, non à partir de leur ordre. C'est toujours bon à savoir !"

Alors si le nom change et que l'ordre n'a pas d'importance ?? Merci

Voir tous les commentaires