1

我在使用 Doctrine/Symfony2 prePersist/preUpdate 监听器时遇到了问题。

多对一关系中有两个实体(一个位置可以被多个人引用)。我构建了一个表单,我在其中执行了一些 AJAX-Stuff 来帮助用户为已经存在的新人员选择一个位置。因此,我使用的是“entity_id”表单域。我还想让用户可以为数据库中不存在的新人员创建新位置。这由表单中的第二个字段处理,用户可以在其中插入新位置的名称。在持久化人的实体时,我正在检查数据库中是否存在引用的位置。如果没有,我正在生成一个新的位置实体。这是(简而言之)我在 Entity-Class Person 中的 prePersist-Lifecyclecallback:

public function prePersist() {
   if($this->ort == null) 
       $this->ort = new Ort($this->ortsname);
}

当我创建一个新人时,这非常有效。问题是更新程序。因此,当之前有一个位置与此人相关联,并且我想通过相同的过程(使用 preUpdate-Listener)创建一个新位置时,我会收到如下通知:

Notice: Undefined index: 000000004a0010250000000058426bec in ...Doctrine/ORM/UnitOfWork.php line 983

我不知道如何解决这个问题。我认为它必须与位置对象有关,它在引用到 Person 对象之前,但我不知道如何告诉 Entity-Manager 引用到 Person 的 Location-Object 是一个新实体。我还尝试了一个 Listener-Class,例如:

if( $entity instanceof Person) {
    if( $entity->getLocation() == null ) {
         $entity->setLocation( new Location( $entity->getLocatioName() );
         $em->persist($entity->getLocation());
         $em->flush();
    }
}

$em->persist ... 东西应该无关紧要,因为在映射中启用了“cascade={persist}”表示法。

4

1 回答 1

2

我想你会遇到麻烦preUpdate。对于这样的情况,有两件事意味着preUpdate不是最好的事件处理程序:

  • 刷新操作不再识别对传递实体的关联的更改。
  • 强烈建议不要对 EntityManager#persist() 或 EntityManager#remove() 进行任何调用,即使与 UnitOfWork API 结合使用,也不会在刷新操作之外按预期工作。

(这两点取自本节底部: http: //docs.doctrine-project.org/en/2.0.x/reference/events.html#preupdate

此外,preUpdate在 Doctrine 的 flush 操作中调用,flush再次调用会导致问题。

因此,我建议您onFlush改用:http ://docs.doctrine-project.org/en/2.0.x/reference/events.html#onflush

如果你这样做了,你需要告诉 Doctrine 一旦你添加了 Location 之后 Person 实体已经改变了。获取更改后的 Person 对象本身也稍微复杂一些。在你的处理程序中尝试这样的事情onFlush

public function onFlush(OnFlushEventArgs $args)
{
    $em = $args->getEntityManager();
    $uow = $em->getUnitOfWork();

    foreach ($uow->getScheduledEntityUpdates() AS $entity) {
        if ($entity instanceof Person) {
            if ($entity->getLocation() == null ) {
                $entity->setLocation( new Location( $entity->getLocationName() ));

                // have to tell Doctrine that the Location has been updated
                $cmf = $args->getEntityManager()->getMetadataFactory();
                $class = $cmf->getMetadataFor(get_class($entity));
                $args->getEntityManager()->getUnitOfWork()->computeChangeSet($class, $entity); // don't use recomputeSingleEntityChangeSet here - that doesn't care about relationships
            }
        }
    }
}
于 2012-12-07T10:51:20.867 回答