Captain Nemo
Captain Nemo

Reputation: 346

Symfony 5 - Return current user data in Trait doesn't work

I created a trait to add two property/column "user_created" and "user_updated" in each Entity (in the same philosophy as "Timestamptable" trait, found on Web)

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface\UserInterface;

trait UserTrack
{
    /**
        * @ORM\ManyToOne(targetEntity=User::class)
    */      
    private $createdUser;
    
    /**
        * @ORM\ManyToOne(targetEntity=User::class)
    */  
    private $updatedUser;
    
    private $security;
    private $me;
    

    public function __construct(Security $security, UserInterface $user)
    {
        $this->security = $security;
        // $this->me = $this->getUser()->getId();  //ERROR
        // $this->me = $this->security->getUser()->getId();  //ERROR
        // $this->me = $user->getId(); //ERROR
    }       
    
    
    
    /**
        * @ORM\PrePersist
    */
    public function setCreatedUserAutomatically()
    {
        if ($this->getCreatedUser() === null) {
            $this->setCreatedUser($this->me);
        }
    }
    
    /**
        * @ORM\PreUpdate
    */
    public function setUpdatedUserAutomatically()
    {
        $this->setUpdatedUser($this->me);
    }
}       

As you can see, i added a "construct" method trying to get my User object but it doesn't work..

Could you help me ?

Thanks !

Upvotes: 2

Views: 1323

Answers (1)

Captain Nemo
Captain Nemo

Reputation: 346

Thanks to Jakumi and Julien B, following code make the job :

EventListener\EntityListener.php

<?php
namespace App\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class EntityListener
{
    private $tokenStorage;
    
    public function __construct(TokenStorageInterface $tokenStorage = null) 
    {
        $this->tokenStorage = $tokenStorage;
    }
    
    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if (null !== $currentUser = $this->getUser()) {
            $entity->setCreatedUser($currentUser);
        }
    }       
    
    public function preUpdate(LifecycleEventArgs $args)
    {       
        $entity = $args->getEntity();
        if (null !== $currentUser = $this->getUser()) {
            $entity->setUpdatedUser($currentUser);
        }
    }
    
    public function getUser()
    {
        if (!$this->tokenStorage) {
            throw new \LogicException('The SecurityBundle is not registered in your application.');
        }
        
        if (null === $token = $this->tokenStorage->getToken()) {
            return;
        }
        
        if (!is_object($user = $token->getUser())) {
            // e.g. anonymous authentication
            return;
        }
        
        return $user;
    }
}   

config/services.yaml

my.listener:
    class: App\EventListener\EntityListener
    arguments: ['@security.token_storage']
    tags:
        - { name: doctrine.event_listener, event: prePersist }    
        - { name: doctrine.event_listener, event: preUpdate }

    

Upvotes: 3

Related Questions