2 votes

Symfony2 Listener vs DataFixtures

J'ai enregistré le listener suivant comme un service. Il enregistre l'utilisateur connecté. Cela fonctionne parfaitement. Après avoir sauvegardé l'entité, l'ID utilisateur est dans createdBy et updatedBy. Ok un petit problème : La commande "php app / console doctrine : fixtures : load" lance l'erreur "Call to a member function getUser () on a non-object. C'est un peu compréhensible. Seulement maintenant je dois désactiver à chaque fois le service avant ? Avez-vous une autre solution ?

class UserListener implements EventSubscriber
{
    protected $container;

    public function \_\_construct(ContainerInterface  $container)
    {
        $this->container = $container;
    }

    public function getSubscribedEvents()
    {
        return array(
            Events::prePersist,
            Events::preUpdate
        );
    }

    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();

        if ($entity instanceof Post) {

            $user = $this->container->get('security.context')->getToken()->getUser();

            if (!is\_object($user) || !$user instanceof User) {
                throw new AccessDeniedException();
            }

            $entity->setCreatedBy($user);
            $entity->setUpdatedBy($user);
        }
    }

    /\*\*
     \* @param PreUpdateEventArgs $args
     \*/
    public function preUpdate(PreUpdateEventArgs $args)
    {
        $entity = $args->getEntity();

        $em = $args->getEntityManager();

        if ($entity instanceof Post) {

            $user = $this->container->get('security.context')->getToken()->getUser();

            if (!is\_object($user) || !$user instanceof User) {
                throw new AccessDeniedException();
            }

            $entity->setUpdatedBy($user);

            $uow = $em->getUnitOfWork();
            $meta = $em->getClassMetadata(get\_class($entity));
            $uow->recomputeSingleEntityChangeSet($meta, $entity);
        }
    }
}

1voto

charles Points 2856

Lorsque vous appelez la commande load-fixtures, vous n'êtes pas connecté. Peut-être $this->container->get('security.context')->getToken() retourne null ?

0voto

webDEVILopers Points 374

J'ai eu un auditeur similaire à et j'essayais de sauvegarder une entité (fictive) ("Post" dans votre cas). Bien sûr, je n'étais pas connecté lorsque j'ai lancé la commande depuis la console.

J'ai ajouté une condition à l'écouteur :

if ($entity instanceof Post) {
    if (null !== $entity->getUser() {
        return;
    }
}

Maintenant, je peux définir un utilisateur (fictif) sur l'entité Post dans mes montages :

$user = $em->getReference('Application\Sonata\UserBundle\Entity\User', 1);
$post = new Post();
$post->setUser($user);

Je ne suis toujours pas sûr que le fait de définir l'utilisateur dans un écouteur d'entité soit une bonne pratique.

Je pense qu'actuellement, la plupart des gens recommanderaient d'utiliser un ValueObject pour "Post" ou au moins un constructeur qui nécessiterait de définir, par exemple, un "name" et un "User".

0voto

stwe Points 538

Mon code final (Symfony 2.6) :

1) L'auditeur :

<?php

namespace AppBundle\Listener;

use AppBundle\Entity\Post;
use AppBundle\Entity\Comment;

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

/**
 * Class BlameableListener
 *
 * @package AppBundle\Listener
 */
class BlameableListener
{
    private $tokenStorage;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function prePersist(LifeCycleEventArgs $args)
    {
        $entity = $args->getEntity();

        if ($entity instanceof Post || $entity instanceof Comment) {
            // is authentication information available?
            if (null !== $this->tokenStorage->getToken()) {
                // get User
                $user = $this->tokenStorage->getToken()->getUser();
                if (is_object($user)) {
                    $entity->setAuthorEmail($user->getEmail());
                }
            }
        }
    }
}

2) Config as Service

services:
    app.blameable.listener:
        class: AppBundle\Listener\BlameableListener
        arguments:
            - "@security.token_storage"
        tags:
            - { name: doctrine.event_listener, event: prePersist }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X