首页 文章

Symfony2 Listener vs DataFixtures

提问于
浏览
2

我已将以下监听器注册为服务 . 这样可以保存登录用户 . 它完美地运作 . 保存实体后,user-id在createdBy和updatedBy中 . 好一点问题:命令“php app / console doctrine:fixtures:load”抛出错误“调用非对象上的成员函数getUser() . 这是可以理解的 . 只有现在我必须每次都禁用之前的服务?你有其他解决方案吗?

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);
        }
    }
}

3 回答

  • 0

    当你调用命令load-fixtures时,你没有登录 . 也许 $this->container->get('security.context')->getToken() 返回null?

  • 0

    我有一个类似的监听器,并试图保存(模拟)实体(在你的情况下“发布”) . 当然,从控制台启动命令时我没有登录 .

    我给听众添加了一个条件:

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

    现在我可以在我的灯具内的Post实体上设置一个(模拟)用户:

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

    仍然不确定是否在实体监听器中设置User是一种很好的做法 .

    我想目前大多数人会建议使用ValueObject作为“Post”或者至少是一个需要设置的构造函数 . “名称”和“用户” .

  • 1

    我的最终代码(Symfony 2.6):

    1)听众:

    <?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)配置为服务

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

相关问题