首页 文章

在Doctrine实体上跟踪字段更改

提问于
浏览
4

我想跟踪对Doctrine Entity字段的更改 . 我使用Symfony 2.5.0和Doctrine 2.2.3 .

到目前为止,我有 EventSubscriber 订阅了 preUpdate . 在这里,我想创建一个新的Entity,它存储新旧值并保存对更新的Entity的引用 .

问题是,我无法找到坚持这个新实体的方法 . 如果 preUpdate 中的 persist()postUpdate 中的 flush() ,如果我只更改一个实体,它就有效 . 如果更改了多个实体,则会收到更改集为空的错误 .

我试着摆弄不同的事件,结果不同 . 空白页面,跟踪entites不会持久化等 .

我认为这应该是一个常见的用例 - 但我找不到例子 .

2 回答

  • 6

    不要使用preUpdate或postUpdate,你会遇到问题 . 请看一下onFlush .

    此时您可以访问完整的变更集,这样您就可以找到已更改的字段,已添加的内容等 . 您还可以安全地保留新实体 . 请注意,docs说,您必须在持久化或更改实体时重新计算更改集 .

    简单的例子我敲了一起,没有经过测试,但类似的东西会得到你想要的东西 .

    public function onFlush(OnFlushEventArgs $args) {
    
        $entityManager = $args->getEntityManager();
        $unitOfWork = $entityManager->getUnitOfWork();
        $updatedEntities = $unitOfWork->getScheduledEntityUpdates();
    
        foreach ($updatedEntities as $updatedEntity) {
    
            if ($updatedEntity instanceof YourEntity) {
    
                $changeset = $unitOfWork->getEntityChangeSet($updatedEntity);
    
                if (!is_array($changeset)) {
    
                    return null;
                }
    
                if (array_key_exists('someFieldInYourEntity', $changeset)) {
    
                    $changes = $changeset['someFieldInYourEntity'];
    
                    $previousValueForField = array_key_exists(0, $changes) ? $changes[0] : null;
                    $newValueForField = array_key_exists(1, $changes) ? $changes[1] : null;
    
                    if ($previousValueForField != $newValueForField) {
    
                        $yourChangeTrackingEntity = new YourChangeTrackingEntity();
                        $yourChangeTrackingEntity->setSomeFieldChanged($previousValueForField);
                        $yourChangeTrackingEntity->setSomeFieldChangedTo($newValueForField);
    
                        $entityManager->persist($yourChangeTrackingEntity);
                        $metaData = $entityManager->getClassMetadata('YourNameSpace\YourBundle\Entity\YourChangeTrackingEntity');
                        $unitOfWork->computeChangeSet($metaData, $yourChangeTrackingEntity);
                    }
                }
            }
        }
    }
    
  • 2

    您可能对EntityAudit bundle感兴趣 .

    它允许配置应跟踪哪些实体 . 然后介绍了数据库修订的概念 . 每个修订版都有时间戳,用户名和受影响的实体列表 .

    然后,您可以找到影响特定实体的所有修订:

    $revisions = $auditReader->findRevisions('AppBundle\Entity\Article', 1);
    

    或在特定版本中实例化它:

    $oldArticle = $auditReader->find(
      'AppBundle\Entity\Article',
      $id = 1,
      $rev = 2
    );
    

    这样您就可以轻松地比较实体的当前状态和旧状态 .

    该软件包还附带了示例视图,演示了如何显示修订列表,比较不同版本的对象等 .

    selecting comparison

    comparison view

相关问题