2

我正在尝试在 symfony2 中运行控制台命令,其中某个类的某些属性正在更新。其中一个属性有一个相应的reviewBy-property,它是由可责备行为设置的,如下所示:

/**
 * @var bool
 * @ORM\Column(name="public_cmt", type="boolean", nullable=true)
 */
private $publicCmt;

/**
 * @var User $publicCmtReviewedBy
 *
 * @Gedmo\Blameable(on="change", field="public_cmt")
 * @ORM\ManyToOne(targetEntity="My\Bundle\EntityBundle\Entity\User")
 * @ORM\JoinColumn(name="public_cmt_reviewed_by", referencedColumnName="id", nullable=true)
 */
private $publicCmtReviewedBy;

当我运行任务时,没有可以“责备”的用户,所以我得到以下异常:

[Doctrine\ORM\ORMInvalidArgumentException]                                   
EntityManager#persist() expects parameter 1 to be an entity object, NULL given.

但是我也不能禁用可责备,因为在我开始任务并以编程方式尝试通过以下方式设置用户时,它还没有注册为过滤器:

// create the authentication token
        $token = new UsernamePasswordToken(
            $user,
            null,
            'main',
            $user->getRoles());
        // give it to the security context
        $this->getService('security.context')->setToken($token); 

不起作用。有人有想法吗?

4

3 回答 3

4

如果您使用 StofDoctrineExtensionsBundle,您可以简单地执行以下操作:

$this->container->get('stof_doctrine_extensions.listener.blameable')
            ->setUserValue('task-user');

见:https ://github.com/stof/StofDoctrineExtensionsBundle/issues/197

于 2015-10-15T22:29:41.483 回答
2

首先,我不确定“字段”是否关心您是否使用数据库列或属性,但您可能需要将其更改为field="publicCmt".

你应该做的是覆盖 Blameable Listener。我假设您正在使用 StofDoctrineExtensionsBundle。首先在您的配置中覆盖:

# app/config/config.yml
stof_doctrine_extensions:
    class:
        blameable: MyBundle\BlameableListener

现在只需扩展现有的侦听器。您有几个选择 - 或者您希望允许 NULL 值(不归咎),或者您希望拥有一个默认用户。比如说你想跳过持久化并允许一个空值,你可以这样覆盖:

namespace MyBundle\EventListener;

use Gedmo\Blameable\BlameableListener;

class MyBlameableListener extends BlameableListener
{
    public function getUserValue($meta, $field)
    {
        try {
            $user = parent::getUserValue($meta, $field);
        }
        catch (\Exception $e) {
            $user = null;

        return $user;
    }

    protected function updateField($object, $ea, $meta, $field)
    {
        if (!$user) {
            return;
        }

        parent::updateField($object, $ea, $meta, $field);
    }
}

所以它首先尝试使用父getUserValue()函数来抓取用户,如果没有,它会返回null。我们必须放入一个 try/catch,因为Exception如果没有当前用户,它会抛出一个。现在在我们的updateField()函数中,如果没有用户,我们根本不做任何事情。

免责声明-updateField()您可能仍然需要该功能的某些部分...我尚未对此进行测试。

这只是一个例子。另一个想法是有一个默认的数据库用户。您可以使用特定用户名将其放入配置文件中。然后,如果安全令牌中没有用户,则不要返回 null,而是可以从数据库中获取默认用户并使用它(当然,您也必须在服务中注入实体管理器)。

于 2014-12-23T03:35:31.393 回答
2

使用相同的 config.yml-entry 对上述答案进行轻微修改:我们可以检查是否设置了用户,如果没有:因为我们可以访问 updateField 方法中的对象管理器,所以获取一个默认用户,设置它并然后执行父方法。

namespace MyBundle\EventListener;

use Gedmo\Blameable\BlameableListener;

class MyBlameableListener extends BlameableListener
{
    protected function updateField($object, $ea, $meta, $field)
    {
        // If we don't have a user, we are in a task and set a default-user
        if (null === $this->getUserValue($meta, $field)) {
            /*  @var $ur UserRepository */
            $ur       = $ea->getObjectManager()->getRepository('MyBundle:User');
            $taskUser = $ur->findOneBy(array('name' => 'task-user'));
            $this->setUserValue($taskUser);
        }
        parent::updateField($object, $ea, $meta, $field);
    }
}
于 2014-12-29T11:27:02.187 回答