2012-11-12 9 views
15

Ich habe einen Logout-Listener, an dem ich eine Flash-Nachricht mit einer Abmeldebestätigungsmeldung einrichten möchte.Symfony 2 - Einstellen einer Flash-Nachricht außerhalb des Controllers

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; 
    } 
} 

Hier ist meine services.yml (wie es dazu gehört):

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

Dies erzeugt einen Fehler:

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

Wie kann ich in diesem eine flashBag Nachricht gesetzt Kontext?

Wie bekomme ich auch Zugriff auf den Router, damit ich die URL generieren kann (über $ this-> router-> generate ('Login')) anstatt eine fest codierte URL zu übergeben?

Auflösung Bemerkung

Um den Blitz zu arbeiten, müssen Sie Ihre security.yml Config nicht ungültig machen die Sitzung beim Abmelden sagen; Andernfalls wird die Sitzung zerstört und Ihr Flash wird nie angezeigt.

Antwort

21

Sie sollten die Dienste für Sitzung und Router in den LogoutListener injizieren und sie verwenden, um diese Aufgaben auszuführen. Dies ist so, wie es in yml zu tun:

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

Dann in der Klasse schreiben Sie:

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; 
    } 
    [...] 

Wenn Sie die Sitzung verwenden möchten können Sie jetzt einfach sagen:

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

Und auf die gleiche Weise können Sie den Router-Dienst verwenden, um Routen zu generieren.

+0

ich meine services.yml hinzugefügt. Wie füge ich die Dienste hinzu? Ich nehme an, dass ich Argumente verwenden muss, aber ich bin mir nicht sicher über die Syntax, um diese zu injizieren. – doremi

+0

Dies zeigt Ihnen ein grundlegendes Beispiel zum Injizieren von Diensten, lesen Sie hier mehr: http://symfony.com/doc/current/book/service_container.html –

+1

Meine Sitzung wird anscheinend zerstört, so dass der Flash gelöscht wird. Ich dachte, die eigentliche Abmeldung wurde bereits gemacht, bevor onLogoutSuccess() aufgerufen wird? – doremi

2

Sie können das Session-Objekt bekommen (wie auch jede andere Dienstleistung) Trog die Service-Container:

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

Die Art und Weise an die Service-Container auf verschiedene Arten zugreifen:

  • Aus ein Controller oder eine Container-bewusste Klasse: benutze $ this-> get ('session');
  • Von einer Dienstleistung: Sie haben den Service Container-Objekt zu injizieren als Aldo
  • Said
+4

Dieser Ansatz funktioniert, aber es ist nicht der richtige Weg, die Abhängigkeitsinjektion durchzuführen. Sie sollten es vermeiden, den Container überallhin zu injizieren, dh den Container zum Implementieren eines Service-Locator-Musters zu verwenden, das zwei wesentliche Nachteile hat: Alle Ihre Klassen (dh Ihr Modell) hängen vom Dienst und nicht von anderen relevanten Teilen des Systems ab unmöglich, sie außerhalb von symfony wiederzuverwenden) und alle Abhängigkeiten werden zur Laufzeit und nicht zur "Kompilierzeit" gelöst, dh wenn symfony den Container vor dem Bootstrapping ablegt. Injizieren Sie nur die Dienste, die Sie benötigen, das ist die beste Vorgehensweise! –

+1

Sie haben einen Punkt :) – Xocoatzin

Verwandte Themen