2012-11-12 28 views
15

Tôi có Trình xử lý đăng xuất nơi tôi muốn đặt thông báo flash hiển thị thông báo xác nhận đăng xuất.Symfony 2 - Cài đặt thông báo Flash ngoài 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; 
    } 
} 

Đây là services.yml của tôi (vì nó gắn liền với điều này):

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

này được tạo ra một lỗi:

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

Làm thế nào để tôi đặt một thông điệp flashBag trong này bối cảnh?

Ngoài ra, làm cách nào để có quyền truy cập vào bộ định tuyến để tôi có thể tạo url (qua $ this-> router-> generate ('login')) thay vì chuyển vào url được mã hóa cứng?

Nghị quyết Note

Để có được flash để làm việc, bạn phải nói với cấu hình security.yml của bạn không làm mất hiệu lực phiên giao dịch ngày logout; nếu không, phiên sẽ bị hủy và đèn flash của bạn sẽ không bao giờ xuất hiện.

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

Trả lời

21

Bạn nên tiêm dịch vụ cho phiên và bộ định tuyến vào LogoutListener và sử dụng chúng để thực hiện các tác vụ này. Đây là cách để làm điều đó trong yml:

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

Sau đó, trong lớp học của bạn, bạn viết:

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

Khi bạn muốn sử dụng phiên bây giờ bạn chỉ có thể nói:

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

Và trong cùng một cách bạn có thể sử dụng dịch vụ router để tạo ra các tuyến đường.

+0

Tôi đã thêm services.yml của mình. Làm cách nào để thêm dịch vụ? Tôi đoán tôi cần phải sử dụng các đối số, nhưng tôi không chắc chắn về cú pháp để tiêm các đối số này. – doremi

+0

Điều này cho bạn thấy một ví dụ cơ bản về dịch vụ tiêm chích, đọc thêm tại đây: http://symfony.com/doc/current/book/service_container.html –

+1

Phiên của tôi dường như bị phá hủy để đèn flash bị xóa. Tôi nghĩ rằng đăng xuất thực tế đã được thực hiện trước khi trênLogoutSuccess() được gọi là? – doremi

2

Bạn có thể lấy đối tượng Session (cũng như bất kỳ dịch vụ khác) trough container dịch vụ:

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

Cách bạn có thể truy cập vào các thùng chứa dịch vụ theo nhiều cách khác nhau:

  • Từ một bộ điều khiển hoặc bất kỳ lớp nhận thức container nào: chỉ cần sử dụng $ this-> get ('session');
  • Từ dịch vụ: bạn phải tiêm đối tượng vùng chứa dịch vụ như Aldo Said
+4

Cách tiếp cận này hoạt động nhưng nó không phải là cách chính xác để làm tiêm phụ thuộc. Bạn nên tránh tiêm container ở khắp mọi nơi, sử dụng container để thực hiện mẫu định vị dịch vụ, có hai nhược điểm chính: tất cả các lớp của bạn (tức là mô hình của bạn) sẽ phụ thuộc vào dịch vụ chứ không phải trên các phần thích hợp khác của hệ thống không thể sử dụng lại chúng bên ngoài symfony) và tất cả các phụ thuộc sẽ được giải quyết trong thời gian chạy thay vì tại "compile-time", tức là khi symfony đổ container trước khi bootstrapping. Chỉ tiêm các dịch vụ bạn cần, đó là cách thực hành tốt nhất! –

+1

Bạn có một điểm :) – Xocoatzin

Các vấn đề liên quan