Search code examples
symfonydoctrine-ormsymfony-3.2

Get current logged in user in entity


I want to create some virtual properties for an entity in an n:m relation.

I have an User, an Achievment and an AchievementUser entity. The value an user have in an Achievement is stored in the field value in the entity AchievementUser.

User -------- 1:n -------- AchievementUser -------- n:1 -------- Achievement
name:String                value:Integer                         name:String
[...]                                                            [...]

Now I want to return the value an user have in an achievement with the achievement itself. So I need a virtual property and a method getValue() in the Achievement entity, but to get the corresponding AchievementUser object, I need the ID of the current logged in user.

How can I get this? Or is there an other possiblility to get the user value for an achievement? Thanks for your help!

Edit: I only have an API based application. Only the serializer executes the Getter method. Here is the content of my serializer file:

virtual_properties:
    getValue:
        serialized_name: value
        type: integer
        groups: ['achievement_default']

Solution

  • You can implement a method in the Achievement entity and pass the current authenticated user into it from your controller of twig template.

    use Doctrine\Common\Collections\Criteria;
    
    // ...
    
    /**
     * @return Collection
     */
    public function getAchievementUsers(User $user)
    {
        $criteria = Criteria::create()->where(Criteria::expr()->eq('user', $user));
    
        return $this->achievementUsers->matching($criteria);
    }
    

    In case of using a JMS serializer, you can add a virtual field and fill it with data using getAchievementUsers method by defining a serialization listener and injecting the TokenStorage to retrieve the current authenticated user.

    <?php
    
    namespace AppBundle\Listener\Serializer;
    
    ...
    use JMS\Serializer\GenericSerializationVisitor;
    use JMS\Serializer\EventDispatcher\ObjectEvent;
    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
    
    class AchievementSerializerListener
    {
        /**
         * @var User
         */
        protected $currentUser;
    
        /**
         * @param TokenStorage $tokenStorage
         */
        public function __construct(TokenStorage $tokenStorage)
        {
            $this->currentUser = $tokenStorage->getToken()->getUser();
        }
    
        /**
         * @param ObjectEvent $event
         */
        public function onAchievementSerialize(ObjectEvent $event)
        {
            if (!$this->currentUser) {
                return;
            }
    
            /** @var Achievement $achievement */
            $achievement = $event->getObject();
    
            /** @var GenericSerializationVisitor $visitor */
            $visitor = $event->getVisitor();
    
            $visitor->setData(
                'achievement_users',
                $achievement->getAchievementUsers($this->currentUser)
            );
        }
    }
    

    services.yml

      app.listener.serializer.achievement:
            class: AppBundle\Listener\Serializer\AchievementSerializerListener
            arguments:
              - '@security.token_storage'
            tags: [ { name: jms_serializer.event_listener, event: serializer.post_serialize, class: AppBundle\Entity\Achievement, method: onAchievementSerialize } ]