2012-11-12 12 views
15

Ho un listener di disconnessione in cui desidero impostare un messaggio flash che mostri un messaggio di conferma di logout.Symfony 2 - Impostazione di un messaggio flash all'esterno del controller

namespace Acme\MyBundle\Security\Listeners; 

use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface; 
use Symfony\Component\Security\Core\SecurityContext; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\RedirectResponse; 

class LogoutListener implements LogoutSuccessHandlerInterface 
{ 
    private $security; 

    public function __construct(SecurityContext $security) 
    { 
    $this->security = $security; 
    } 

    public function onLogoutSuccess(Request $request) 
    { 
    $request->get('session')->getFlashBag()->add('notice', 'You have been successfully been logged out.'); 

    $response = new RedirectResponse('login'); 
    return $response; 
    } 
} 

Ecco il mio services.yml (per quello che attiene a questo):

logout_listener: 
    class: ACME\MyBundle\Security\Listeners\LogoutListener 
    arguments: [@security.context] 

Questo sta generando un errore:

Fatal error: Call to a member function getFlashBag() on a non-object 

Come faccio a impostare un messaggio in questo flashBag contesto?

Inoltre, come accedere al router in modo da poter generare l'url (tramite $ this-> router-> generate ('login')) invece di passare in un URL hardcoded?

Risoluzione Nota

Per ottenere il flash a lavorare, è necessario informare il config security.yml non invalida la sessione al logout; in caso contrario, la sessione verrà distrutta e il tuo flash non verrà mai visualizzato.

logout: 
    path: /logout 
     success_handler: logout_listener 
     invalidate_session: false 

risposta

21

È necessario immettere i servizi per sessione e router nel LogoutListener e utilizzarli per eseguire queste attività. Questo è il modo di farlo in yml:

logout_listener: 
class: ACME\MyBundle\Security\Listeners\LogoutListener 
arguments: [@security.context, @router, @session] 

Poi nella classe si scrive:

class LogoutListener implements LogoutSuccessHandlerInterface 
{ 
    private $security; 
    private $router; 
    private $session; 

    public function __construct(SecurityContext $security, Router $router, Session $session) 
    { 
     $this->security = $security; 
     $this->router = $router; 
     $this->session = $session; 
    } 
    [...] 

Quando si desidera utilizzare la sessione ora si può solo dire:

$this->session->getFlashBag()->add('notice', 'You have been successfully been logged out.'); 

E allo stesso modo è possibile utilizzare il servizio router per generare percorsi.

+0

ho aggiunto il mio services.yml. Come aggiungo iniettare i servizi? Presumo che ho bisogno di usare argomenti, ma non sono sicuro della sintassi per iniettarli. – doremi

+0

Questo ti mostra un esempio di base riguardo l'iniezione di servizi, leggi di più qui: http://symfony.com/doc/current/book/service_container.html –

+1

A quanto pare la mia sessione viene distrutta e il flash viene cancellato. Pensavo che l'attuale disconnessione fosse già stata effettuata prima che onLogoutSuccess() venisse chiamato? – doremi

2

È possibile ottenere l'oggetto Session (così come qualsiasi altro servizio) Trough il contenitore di servizi:

$session = $ServiceContainer->get('session'); 
$session->setFlash('notice', 'Message'); 

Il modo in cui è possibile accedere al contenitore di servizio in diversi modi:

  • Da un controller o una classe a conoscenza del contenitore: usa $ this-> get ('session');
  • Da un servizio: è necessario per iniettare l'oggetto contenitore servizio come Aldo Detto
+4

Questo approccio funziona ma non è il modo corretto di fare l'iniezione di dipendenza. Dovresti evitare di iniettare il contenitore ovunque, cioè utilizzare il contenitore per implementare un modello di localizzazione del servizio, che ha due principali svantaggi: tutte le tue classi (cioè il tuo modello) dipenderanno dal servizio piuttosto che da altre parti pertinenti del sistema (rendendolo impossibile riutilizzarli al di fuori di symfony) e tutte le dipendenze verranno risolte in fase di esecuzione piuttosto che in "tempo di compilazione", ovvero quando symfony scarica il contenitore prima dell'avvio automatico. Inietti solo i servizi di cui hai bisogno, questa è la migliore pratica! –

+1

Hai un punto :) – Xocoatzin

Problemi correlati