使用doctrine和sonata-admin实现日志的最佳方法

时间:2015-06-02 11:56:56

标签: php symfony doctrine-orm doctrine

我有一个案例,我想记录实体上发生的每一个变化。我使用了sonata-admin和doctrine管理包。我尝试了很多东西,但我想出了这个案例的最佳方法是什么。

第一次尝试是使用字段类型(创建/更新),更改(数组)以及相关实体类和ID创建ChangeLog实体。

我为postUpdate和postPersist事件设置了一个监听器:

appbundle.listen.ChangeLog:
    class: AppBundle\Listener\ChangeLogListener
    arguments: [@service_container]
    tags:
        - { name: doctrine.event_listener, event: postUpdate}
        - { name: doctrine.event_listener, event: postPersist}

相关的听众:

public function prePersist(LifecycleEventArgs $args)
{
    $this->buildLog($args, ChangeLog::TYPE_CREATE);
}

public function preUpdate(LifecycleEventArgs $args){
    $this->buildLog($args, ChangeLog::TYPE_UPDATE);
}

private function buildLog(LifecycleEventArgs $args, $type)
{
    $entity = $args->getEntity();

    $clHelper = ChangeLogHelper::getInstance();

    if ($entity instanceof ChangeLog) return;

    $em = $args->getEntityManager();
    $changes = $em->getUnitOfWork()->getEntityChangeSet($entity);
    $user = $this->container->get('security.context')->getToken()->getUser();

    $cl = new ChangeLog();
    $cl->setUser($user);
    $cl->setDate(new \DateTime());
    $cl->setChangeset($changes);
    $cl->setType($type);
    $cl->setEntityName(get_class($entity));
    $cl->setDescription('');
    $cl->setEntityId($entity->getId());
    $cl->setRefGroup($clHelper->getRefId());

    $em->persist($cl);
    $em->flush();
}

这适用于某些实体,但只要我有更多关系,我就会收到错误:

Catchable Fatal Error: Argument 3 passed to Doctrine\ORM\Event\PreUpdateEventArgs::__construct() ....

我发现无法解决这个问题,但我觉得它是因为监听器将被多次调用(对于实体本身和每个关系)而且最好在所有监听器的末尾刷新而不是每次调用它,但我没有看到任何方式使用post事件监听器设置。

经过几个小时的调试后,我认为如果我在ChangeLog实体上与其他实体之间存在多态关系可能会更好,我可以使用prePersist / preUpdate听众,所以我不必自己保留对象,并将其设置为已更改对象上的关系,并使用适当的级联。而且我试图避免在教义事件中使用entityManager。几个小时后,我仍然陷入困境,我无法找到一种与学说有这种关系的方法。基本上是一对多,有一个额外的列,其中定义了目标实体。

我试图让它与doctrine继承(STI和CTI)一起工作,但后来我的日志字段在实体本身上,而不再分离,我不想要。我试图在没有ChangeLog实体的拥有方的情况下解决这个问题,但是我无法在更改的实体上设置ChangeLog实体,因为它将被忽略。但我不知道如何定义拥有方面,基本上是对所有其他实体的引用,我现在不认为它可以用学说。

使用映射的超类和OneToMany关系,我将获得每个实体的连接表或连接列,这也是一种混乱。

0 个答案:

没有答案