I have a logout Listener where I'd like to set a flash message showing a logout confirmation message.
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;
}
}
Here is my services.yml (as it pertains to this):
logout_listener:
class: ACME\MyBundle\Security\Listeners\LogoutListener
arguments: [@security.context]
This is generating an error:
Fatal error: Call to a member function getFlashBag() on a non-object
How do I set a flashBag message in this context?
Also, how do get access to the router so I can generate the url (via $this->router->generate('login')) instead of passing in a hard-coded url?
Resolution Note
To get the flash to work, you must tell your security.yml config not invalidate the session on logout; otherwise, the session will be destroyed and your flash will never appear.
logout:
path: /logout
success_handler: logout_listener
invalidate_session: false
You should inject the services for session and router into the LogoutListener and use them to perform these tasks. This is the way to do it in yml:
logout_listener:
class: ACME\MyBundle\Security\Listeners\LogoutListener
arguments: [@security.context, @router, @session]
Then in your class you write:
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;
}
[...]
When you want to use the session now you can just say:
$this->session->getFlashBag()->add('notice', 'You have been successfully been logged out.');
And in the same way you can use the router service to generate routes.
You can get the Session object (as well as any other service) trough the service container:
$session = $ServiceContainer->get('session');
$session->setFlash('notice', 'Message');
The way you can access to the service container in different ways:
The answers are very old on this post. 10 years later (2022), Symfony allows to deal with flashes very easily outside of a controller using the FlashBagInterface
:
<?php
namespace App\Service;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
class MyService
{
private $flash;
public function __construct(FlashBagInterface $flash)
{
$this->flash = $flash;
}
public function myRandomMethod(): string
{
// ...
$this->flash->add('success', 'This is a success!');
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With