Another Symfony mistery
You might have been struggling to fetch the logged-in user from a listener that includes a UserService class which contains the logic of fetching the logged-in user.
Let's take the below code as an example:
//UserService.php <?php namespace App\Service; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; class UserService { private $tokenStorage; private $currentUser; /** * @required */ public function setSecurityContext(TokenStorageInterface $tokenStorage) { $token = $tokenStorage->getToken(); if ($token) { $this->currentUser = $token->getUser(); } } public function getCurrentUser() { return $this->currentUser; } } ?>
//MyListner <?php namespace App\Listener; use Doctrine\Persistence\Event\LifecycleEventArgs; class MyListener { private $userService; public function __construct(UserService $userService) { $this->userService = $userService; } public function onFlush(LifecycleEventArgs $args) { $currentUser = $this->userService->getCurrentUser(); var_dump($currentUser); // prints NULL } } ?>
Why the currentUser is NULL ?
The answer: Doctrine listeners are called whenever a corresponding event occurs. Initialization of them may occur before the security context.
You have two options here:
The first one: inject your TokenStorage directly in your Listener and retrieve the token inside your event handler.
//MyListner <?php namespace App\Listener; use Doctrine\Persistence\Event\LifecycleEventArgs; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; class MyListener { private $tokenStorage; public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } public function onFlush(LifecycleEventArgs $args) { $currentUser = $this->tokenStorage->getToken()->getUser(); var_dump($currentUser); // prints a UserInterface object } } ?>
The second one: Fetch the token inside the getCurrentUser
method.
//UserService.php <?php namespace App\Service; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; class UserService { private $tokenStorage; private $currentUser; public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } public function getCurrentUser(TokenStorageInterface $tokenStorage) { $token = $tokenStorage->getToken(); if ($token && is_null($this->currentUser)) { $this->currentUser = $token->getUser(); } return $this->currentUser; } } ?>
The hidden trick is that you have to call the getToken
method in order to get a fresh token.
That was it, I hope this blog post was helpful.
Cheers
Top comments (0)