2013-05-18 6 views
6

Sto tentando di impostare le impostazioni internazionali in base alle preferenze dell'utente corrente che sono memorizzate nel DB.symfony 2 imposta le impostazioni locali in base alle preferenze utente memorizzate nel DB

La nostra classe Utente ha quindi un linguaggio getPreferred che restituisce un identificativo di locale ('en', 'fr_FR', ecc.).

Ho considerato il seguente approccio:

  • registrare un "locale" servizio di ascolto che sottoscrive i KernelEvents :: evento RICHIESTA.
  • questo servizio ha accesso al contesto di sicurezza (tramite il suo costruttore)
  • questo metodo onKernelRequest di questo servizio tenta di richiamare l'utente dal contesto di sicurezza, ottenere le impostazioni locali preferite dell'utente e impostarlo come locale della richiesta.

Sfortunatamente, questo non funziona. Quando viene richiamato il metodo onRequestEvent del servizio listener "locale", il contesto di sicurezza non ha un token. Sembra che il listener di contesto sia invocato in una fase molto avanzata (con una priorità pari a 0), ed è impossibile dire al mio listener "locale" di essere eseguito prima del contesto di sicurezza.

Qualcuno sa come risolvere questo approccio o suggerirne un altro?

+0

Ho trovato una risposta imperfetta al mio problema, per quello che vale: Nel listener di eventi del kernel, posso ottenere il token di sicurezza dalla sessione e digitalizzarlo, e quindi ottenere l'utente. Sfortunatamente, questo si basa sulla conoscenza del "contextKey" per il firewall, che è praticamente codificato. Ad esempio, se il firewall è "principale", il token può essere ottenuto dalla sessione con: token $ = $ session-> get ('_ security_main'); Questa logica viene rimossa da ContextListener. Ma il listener di contesto ottiene l'id del firewall passato durante la configurazione. – user1447137

+0

Hai provato a iniettare security_context? Quindi puoi ottenere il token e l'utente semplicemente dal contesto. –

+0

Pazi, l'iniezione del contesto di sicurezza non funziona. Questo è il punto centrale di questo biglietto. – user1447137

risposta

2

si può essere interessati in chi ascolta locale, che ho postato in questa risposta: Symfony2 locale detection: not considering _locale in session

Edit: Se un utente cambia la sua lingua nel profilo, non è un problema. Puoi collegare all'evento di modifica del profilo se stai utilizzando FOSUserBundle (master). Altrimenti nel controller del tuo profilo, se stai utilizzando un sistema creato da te stesso. Ecco un esempio per i FOSUserBundle:

<?php 
namespace Acme\UserBundle\EventListener; 
use FOS\UserBundle\Event\FormEvent; 
use FOS\UserBundle\FOSUserEvents; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 

class ChangeLanguageListener implements EventSubscriberInterface 
{ 
    public static function getSubscribedEvents() 
    { 
     return array(
       FOSUserEvents::PROFILE_EDIT_SUCCESS => 'onProfileEditSuccess', 
     ); 
    } 

    public function onProfileEditSuccess(FormEvent $event) 
    { 
     $request = $event->getRequest(); 
     $session = $request->getSession(); 
     $form = $event->getForm(); 
     $user = $form->getData(); 
     $lang = $user->getLanguage(); 

     $session->set('_locale', $lang); 
     $request->setLocale($lang); 
    } 
} 

e nel services.yml

services: 
    acme.change_language: 
     class: Acme\UserBundle\EventListener\ChangeLanguageListener 
     tags: 
      - { name: kernel.event_subscriber } 

per più sessioni nel browser multipla non è un problema, in quanto ogni nuova sessione richiede un nuovo login. Hmm, ok, non dopo aver cambiato la lingua, in quanto solo la sessione corrente sarebbe stata aggiornata. Ma puoi modificare LanguageListener per supportarlo.
E il caso in cui un amministratore cambia la lingua dovrebbe essere insignificante.

+0

Apprezzo la risposta, che è utile in una certa misura. Avevo preso in considerazione un simile approccio nelle prime fasi, ma diversi casi d'uso richiederebbero ulteriore logica per essere supportati, come ad esempio: l'utente che modifica la lingua preferita durante l'accesso (richiederebbe l'aggiornamento della sessione), più sessioni (ad es.l'utente ha effettuato l'accesso tramite diversi browser) e la lingua preferita dall'utente è stata modificata direttamente in DB (ad esempio tramite la pagina di amministrazione). Questo mi fa chiedere se non c'è una risposta più diretta al problema. – user1447137

+0

Vedi la mia modifica. –

+0

Sì, funzionerà, ed è certamente una soluzione migliore quella che ho trovato, ma coinvolge molte parti mobili. A causa delle semplici circostanze della mia app, andrò con la mia soluzione dichiaratamente sub-ottimale (dato che mi occupo solo di 1 firewall, posso semplicemente iniettare il suo id nel mio listener e usarlo per recuperare il token di sicurezza dalla sessione) . Grazie molto. – user1447137