symfonytwig

Flash doesn't show up on app_default


I try to use an app_flash on my symfony app, it work everywhere but when I try to display a flash on my app_default it doesn't work. I tried to dump but it's empty like nothing is send.

I have a simple login controller to connect my users with this code:

 #[Route(path: '/login', name: 'app_login')]
    public function login(AuthenticationUtils $authenticationUtils): Response
    {
        $error = $authenticationUtils->getLastAuthenticationError();
        $lastUsername = $authenticationUtils->getLastUsername();

        if($lastUsername){
            $this->addFlash('success', 'You are logged in.');
            return $this->redirectToRoute('app_default');

        }
        return $this->render('pages/security/login.html.twig', [
            'last_username' => $lastUsername,
            'error' => $error,
        ]);
    }

and my vue index.html.twig contains :

{% block body %}
    <div class="container w-75">
        {% for message in app.flashes('success') %}
            <div class="alert alert-success">
                {{ message }}
            </div>
        {% endfor %}
    </div>
{% endblock %}

Solution

  • $lastUsername will only contain a value if a user tried logging in with the login form but there was an error (e.g. they submitted the wrong password). (You can then echo $lastUsername back in the form so that they can try logging in again with the same username without having to retype it.)

    So if a user logs in successfully on their first try, $lastUsername will remain empty and the flash message will not be set.

    However, the login function is only used to render the login form, you cannot use it to determine if the login was successful. So if you only want to show a flash message when a user has successfully logged in, you should not set the flash message there.

    If you're already using a custom LoginFormAuthenticator (one may have been generated for you if you used make:auth), you can set the flash message in its onAuthenticationSuccess method, right before the redirect:

    class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
    {
    
        // ...
    
        public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
        {
            $request->getSession()->getFlashBag()->add('success', 'You are logged in.');
    
            return new RedirectResponse($this->urlGenerator->generate('app_default'));
        }
    }
    

    If not, you can set it in an event subscriber for the InteractiveLoginEvent:

    namespace App\EventSubscriber;
    
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
    
    class LoginSuccessSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                InteractiveLoginEvent::class => 'onLoginSuccess',
            ];
        }
    
        public function onLoginSuccess(InteractiveLoginEvent $event)
        {
            $request = $event->getRequest();
    
            $request->getSession()->getFlashBag()->add('success', 'You are logged in.');
        }
    }
    
    

    This then sets the flash message and redirects to the default_target_path you have set in security.yaml, or to / if none was set:

    security:
        firewalls:
            main:
                form_login:
                    # ...
                    default_target_path: app_default
    

    But you could also use the LoginSuccessEvent, see the events here: https://symfony.com/doc/current/security.html#authentication-events