preExecute() dans les controller Symfony2
Contrairement à symfony1.x ou à Zend, Symfony2 ne propose pas par défaut un méthode, qui si elle est définie, permet d'exécuter un morceau de code avant toutes les actions d'un controller.
<?php /** * prototype d'une telle fonction dans symfony 1.x * dans un fichier controller, par exemple : * /app/frontend/modules/index/actions/actions.class.php * */ class indexActions extends sfActions public function preExecute() { // Le code écrit ici sera executé avant chacune des actions de ce controlleur. } } ?> <?php /** * prototype d'une telle fonction dans Zend 1.x * dans un fichier controller, par exemple : * /application/controller/indexController.php */ class IndexController extends Zend_Controller_Action { public function init() { // Le code écrit ici sera executé avant chacune des actions de ce controlleur. } } ?>
Toutefois, Symfony2 propose un mécanisme d'event suffisamment avancé pour reproduire un tel comportement.
Il y a trois étapes pour y arriver :
1. Créer un listner
2. Connecter le listner avec le DIC (Dependecy Injection Controller)
3. Implémenter le preExecute()
1. Créer un listner
Il faut créer un répertoire Listner dans votre bundle et y créer une classe pour votre listner.
<?php // Dans le fichier /src/MonPath/MonBundle/Listener/ControllerListener namespace MonPath\MonBundle\Listener; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; // Le nom de la classe est à votre discrétion class ControllerListener { // Le nom de la méthode est également à votre discrétion public function onCoreController(FilterControllerEvent $event) { // Récupération de l'event if(HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) { // Récupération du controller $_controller = $event->getController(); if (isset($_controller[0])) { $controller = $_controller[0]; // On vérifie que le controller implémente la méthode preExecute if(method_exists($controller,'preExecute')) { $controller->preExecute(); } } } } }
2. Connecter le listner avec le DIC
Pour cela on va ajouter un service dans le fichier de configuration du projet (/app/config/config.yml).
- On donne le nom que l'on veut au service (ici : controller.pre_execute_listener).
- Ensuite, on lui dit quelle classe utiliser (celle que nous venons de faire).
- Puis on dit que l'on veut le brancher sur un évènement (name: event_listener).
- Et quel évènement en particulier iil faut écouter (event: kernel.controller).
- Enfin on donne la méthode de la classe à exécuter lorsque l'évènement est appelé (method: onCoreController)
#/app/config/config.yml services: controller.pre_execute_listener: class: MonPath\MonBundle\Listener\ControllerListener tags: - { name: kernel.event_listener, event: kernel.controller, method: onCoreController }
3. Implémenter le preExecute()
Il est maintenant possible de définir dans n'importe quel controller une méthode preExecute() qui sera appelée avant chaque action de ce controller.
Exemple : interdire l'accès à un controller à un utilisateur non loggé
<?php namespace MonPath\MonBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; class MonController extends Controller { public function preExecute() { $user = $this->container->get('security.context')->getToken()->getUser(); if (!is_object($user)) { throw new AccessDeniedException('This user does not have access to this section.'); } } }
Betouar Hamza Wednesday 9 May à 17h12
le listener marche très bien,
merci pour le partage.