Symfony2.8.4 (Erreur)

Bonjour à tous,

Je travaille sur Symfony sur la traduction de mon site.

J’ai appliqué à la lettre ce tutoriel : http://www.benjaminschied.fr/changer-la-langue-dans-symfony-2/#more-148.

Je suis bloqué sur une erreur que je n’arrive pas à corriger.

Est-ce que quelqu’un a déjà rencontré cette erreur ou a une solution?

Voici mon fichier : services.yml

services:
    front_bundle.locale_listener:
         class: FrontBundle\EventListener\LocaleListenere
         arguments: ["%kernel.default_locale%"]
         tags:
             - { name: kermel.event_subscriber }

Voici l’erreur :

InvalidArgumentException in RegisterListenerPass.php line 103:
Service "front_bundle.locale_listener" must implement interface "Symfony\Component\EventDispatcher\EventSubscriberInterface".

Merci par avance !

Je suis pas très cale en Symfony, mais ca m’a l’air assez clair 1 re vue :
tu as créé une classe FrontBundle\EventListener\LocaleListener.
Et cette classe est censée implementer un mécanisme d’écouteur d’evenements.

Pour que Symfony sache manipuler l’instance de ta classe comme un véritable Listener,
il a besoin :

  1. que ta classe implémente (et donc respecte) le contrat d’interface
    Symfony\Component\EventDispatcher\EventSubscriberInterface
  2. et du coup qu’elle expose les méthodes publiques décrites dans cette interface.

C’est bon pour toi ? Sinon hésite pas à demander des précisions

Bonjour Joris,

Je te remercie pour cet éclairement.
Mais j’aurais besoin plus de précisions avec si possible un exemple.

Cdlt,

Bonjour,

Si tu as suivi a la lettre le tuto alors ta Classe doit s’appeler “LocaleListener” or dans ton services.yml tu as écrit qu’elle s’appelle “LocaleListenere” il y a un “e” de trop.

@Tom ne nous a pas montré l’implémentation de sa classe donc on ne sait pas comment il l’a nommé réellement.
Avec ou sans faute de frappe.

Le message d’erreur dans l’eception levée me porte à croire que l’erreur de frappe existe à la fois dans le nom de la classe ET dans le service.yml
Ici Symfony semble avoir trouvé la classe puisqu’il précise seulement qu’elle n’implémente pas l’interface attendue.
Si la faute de de frappe était en cause, il ne trouverait pas du tout la classe
et serait incapable d’en déduire ce qu’elle implémente ou pas.

C’est une hypothèse.
Qu’en penses tu @Jean ?

Effectivement.
Ma config utilise un système de ce type et les erreurs de ce genre sont détectées avant (car un “kermel” traine dans le coin).
Il nous faudra voir sa version réelle de services.yml et de LocaleListener.php.

Attention, Le Bundle JMSSerializer utilise aussi une interface nommée “EventSubscriberInterface” donc si le code a été crée avec un IDE, celui-ci a pu utiliser une interface au lieu de l’autre…

Re,

Je n’ai pas modifié mon fichier LocaleListener et dans le fichier services.yml c’était une erreur de saisie lors de la copie. Mais dans mon fichier je n’ai pas rajouter de (e).

J’utilise l’IDE PHPStorm v.9.0.

Mon fichier LocaleListener :

namespace AppBundle\EventListener;
 
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
class LocaleListener implements EventSubscriberInterface
{
    private $defaultLocale;
 
    public function __construct($defaultLocale = 'fr')
    {
        $this->defaultLocale = $defaultLocale;
    }
 
    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        if (!$request->hasPreviousSession()) {
            return;
        }
 
        // On essaie de voir si la locale a été fixée dans le paramètre de routing _locale
        if ($locale = $request->attributes->get('_locale')) {
            $request->getSession()->set('_locale', $locale);
        } else {
            // Si aucune locale n'a été fixée explicitement dans la requête, on utilise celle de la session
            $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
        }
    }
 
    public static function getSubscribedEvents()
    {
        return array(
            // Doit être enregistré avant le Locale listener par défaut
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

Mon fichier services.yml :

services:
    front_bundle.locale_listener:
         class: FrontBundle\EventListener\LocaleListener
         arguments: ["%kernel.default_locale%"]
         tags:
             - { name: kermel.event_subscriber }

J’ai toujours l’erreur.

Hypothèse #2 : dans service : KERNEL au lieu de KERMEL dans kermel.event_subscriber ?

Hypothèse #3 : ya pas un cache a vider ?

Même avec KERNEL c’est le statu quo.
J’ai vidé le cache également.

Peut être c’est l’hypothèse de @Jean selon laquelle si le code a été crée avec un IDE, celui-ci a pu utiliser une interface au lieu de l’autre…

Mais elles ne doivent pas être dans le même répertoire.

C’est dingue, je ne comprend pas cette erreur.

pour éviter toute confusion dans les namespaces tu peux toujours essayer ca :

use Symfony\Component\EventDispatcher\EventSubscriberInterface as ESI;
(ou n’importe quel autre alias)

puis
class LocaleListener implements ESI

au moins tu tassres que la bonne interface sera implémentée.

Ok je testerai et je te dirai quoi.

Oui son message d’erreur a 2 interprétations possibles:

  • soit la classe n’implémente pas d’interface
  • soit la classe implémente bien un EventSubscriberInterface…mais qui est pas le bon

Théoriquement l’intéret des namespaces est d’éviter ces confusions.
D’où l’intéret d’utiliser des alias à portée locale pour bien expliciter les choses.

J’ai toujours l’erreur:

( ! ) Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Service "front_bundle.locale_listener" must implement interface "Symfony\Component\EventDispatcher\EventSubscriberInterface".' in C:\wamp\www\kids\vendor\symfony\symfony\src\Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass.php on line 103
( ! ) InvalidArgumentException: Service "front_bundle.locale_listener" must implement interface "Symfony\Component\EventDispatcher\EventSubscriberInterface". in C:\wamp\www\kids\vendor\symfony\symfony\src\Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass.php on line 103

Ci-dessous mon fichier FrontController.php :

<?php

namespace Blog\FrontBundle\Controller;

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

class FrontController extends Controller
{
    public function siteAccueilAction()
    {
        return $this->render('FrontBundle:Front:siteAccueil.html.twig');
    }

    public function setLocaleAction($langue = null)
    {
        if($langue != null)
        {
            // On enregistre la langue en session
            $this->get('Session')->set('_locale', $langue);
        }

        // on tente de rediriger vers la page d'origine
        $url = $this->container->get('request')->headers->get('referer');
        if(empty($url)) {
            $url = $this->container->get('router')->generate('front_pageaccueil');
        }
        return new RedirectResponse($url);
    }
}

Et le fichier de route : routing.yml

front_pageaccueil:
    path:     /accueil
    defaults: { _controller: FrontBundle:Front:siteAccueil }

front_pagelangue:
    path:     /accueil/{langue}
    defaults: { _controller: FrontBundle:Front:setLocale }

Je vois que le namespace de ta classe listener commence par AppBundle alors que tu spécifie qu’elle doit se trouver dans FrontBundle du Blog.
Essaye de remettre les bons namespaces pour voir.

euu dans services.yml : kernel pas KERNEL, on est d’accord ?

@Jean, oui justement j’ai modifier le namespace de ma classe listener. Et @Joris, c’est kernel sur mon fichier.

Enfin, j’ai trouvé la solution. En fait, je n’ai pas rajouter le namespace de mon bundle (FrontBundle) dans les fichiers services.yml et LocaleListener.php respectivement :

front_bundle.locale_listener:
         class: Blog\FrontBundle\EventListener\LocaleListener
         arguments: ["%kernel.default_locale%"]
         tags:
             - { name: kernel.event_subscriber }`

et

<?php
namespace Blog\FrontBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
//use Symfony\Component\EventDispatcher\EventSubscriberInterface as ESI;

class LocaleListener implements EventSubscriberInterface
{
    private $defaultLocale;

    public function __construct($defaultLocale = 'fr')
    {
        $this->defaultLocale = $defaultLocale;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        if (!$request->hasPreviousSession()) {
            return;
        }

        // On essaie de voir si la locale a été fixée dans le paramètre de routing _locale
        if ($locale = $request->attributes->get('_locale')) {
            $request->getSession()->set('_locale', $locale);
        } else {
            // Si aucune locale n'a été fixée explicitement dans la requête, on utilise celle de la session
            $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            // Doit être enregistré avant le Locale listener par défaut
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

Merci beaucoup les gars d’avoir pris ce temps précieux pour m’aider.
Je vous dis à bientôt !

2 J'aimes
Human Coders - Le centre de formation recommandé par les développeur·se·s pour les développeur·se·s