2

我已将以下侦听器注册为服务。这将保存登录用户。它完美地工作。保存实体后,用户 ID 位于 createdBy 和 updatedBy 中。好的一个小问题:命令“php应用程序/控制台学说:fixtures:load”抛出错误“调用非对象上的成员函数getUser()。这是可以理解的。只是现在我每次都必须禁用之前的服务?你有其他解决方案吗?

类 UserListener 实现 EventSubscriber
{
    受保护的$容器;

    公共函数 __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    公共函数 getSubscribedEvents()
    {
        返回数组(
            事件::prePersist,
            事件::更新前
        );
    }

    公共函数 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) {
                抛出新的 AccessDeniedException();
            }

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

    /**
     * @param PreUpdateEventArgs $args
     */
    公共函数 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) {
                抛出新的 AccessDeniedException();
            }

            $entity->setUpdatedBy($user);

            $uow = $em->getUnitOfWork();
            $meta = $em->getClassMetadata(get_class($entity));
            $uow->recomputeSingleEntityChangeSet($meta, $entity);
        }
    }
}
4

3 回答 3

1

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

于 2012-05-18T14:18:19.743 回答
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);

仍然不确定在实体侦听器中设置用户是否是一种好习惯。

我想目前大多数人会建议使用 ValueObject 来表示“Post”,或者至少是一个需要设置例如“名称”和“用户”的构造函数。

于 2015-06-12T09:01:47.823 回答
0

我的最终代码(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 }
于 2015-06-17T20:12:07.313 回答