Another Symfony mistery
You might have been struggling fetching 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 corresponding event occurs. Initialization of them may occur before security context.
You have two options here:
The first one : inject yout 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