【问题标题】:Symfony 2 - Setting a Flash Message outside of ControllerSymfony 2 - 在控制器之外设置 Flash 消息
【发布时间】:2012-11-01 03:52:11
【问题描述】:

我有一个注销侦听器,我想在其中设置一条显示注销确认消息的闪烁消息。

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

这是我的 services.yml(与此相关):

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

这会产生错误:

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

如何在这种情况下设置 flashBag 消息?

另外,如何访问路由器以便生成 url(通过 $this->router->generate('login'))而不是传入硬编码的 url?

解决说明

要让闪存正常工作,您必须告诉您的 security.yml 配置不要在注销时使会话无效;否则,会话将被破坏,您的闪存将永远不会出现。

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

【问题讨论】:

    标签: symfony


    【解决方案1】:

    您应该将会话和路由器的服务注入 LogoutListener 并使用它们来执行这些任务。这是在 yml 中的做法:

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

    然后在你的课堂上写:

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

    当你现在想使用会话时,你可以说:

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

    同样你可以使用路由服务来生成路由。

    【讨论】:

    • 我添加了我的 services.yml。如何添加注入服务?我想我需要使用参数,但我不确定注入这些参数的语法。
    • 这向您展示了一个关于注入服务的基本示例,请在此处阅读更多内容:symfony.com/doc/current/book/service_container.html
    • 我的会话显然被破坏了,所以闪存被擦除了。我认为在调用 onLogoutSuccess() 之前已经完成了实际的注销?
    • 我的猜测是注销后调用onLogoutSuccess,是的。但这超出了这个问题的范围,那是关于如何在课堂上使用会话和路由器。
    • 看起来我必须设置一个标志以不使会话 onLogout 无效。见:stackoverflow.com/questions/11043672/symfony-logout-handler
    【解决方案2】:

    您可以通过服务容器获取 Session 对象(以及任何其他服务):

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

    您可以通过不同方式访问服务容器的方式:

    • 从控制器或任何容器感知类:只需使用 $this->get('session');
    • 从服务:您必须像 Aldo Said 那样注入服务容器对象

    【讨论】:

    • 这种方法有效,但它不是进行依赖注入的正确方法。您应该避免在任何地方注入容器,即使用容器来实现服务定位器模式,这有两个主要缺点:您的所有类(即您的模型)将依赖于服务而不是系统的其他相关部分(使其不可能在 symfony 之外重用它们)并且所有依赖关系都将在运行时而不是在“编译时”解决,即当 symfony 在引导之前转储容器时。只注入您需要的服务,这是最佳做法!
    猜你喜欢
    • 2013-02-19
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 2016-01-02
    相关资源
    最近更新 更多