嵌入式表单持久性:获取或创建

时间:2013-07-31 10:01:23

标签: symfony doctrine

我使用Symfony2和doctrine。我目前有一个名为Person的实体。该实体与一些其他实体相关,作为一对多关系(作为多对一单向关系)。我希望每个Person实体都是唯一的(我在数据库中使用UniqueConstraint注释完成的操作)。

要清楚,我将假设我有两个名为Home和Car的实体,它们与目标实体Person具有多对一关系。

然后我使用表单来创建或编辑我的实体Car和Home。在这些表单中,我显示一个嵌入的表单来创建一个Person实体或选择一个现有的实体。我解释一下:我的嵌入表单的第一个字段是该人的名字。当用户键入人员姓名时,将显示现有人员列表(使用JQuery自动完成UI),如果用户选择其中一个,则其他字段将自动完成。

问题是,当用户向现有人提交表单时,我发现了完整性错误(我知道为什么,因为我的唯一约束)。

第一个解决方法之一是将id字段添加为嵌入表单中的隐藏输入。 但随后用户可以编辑其他字段并破坏当前实体。 所以没有。

如果Person已经存在,另一个可能是阻止控制器中的持久性,但是我在许多其他实体中使用它。我将不得不复制我的代码,我不想这样做,因为唯一约束与Person实体有关,而与Car或Home实体无关。 所以没有了。

我正在研究的解决方法是使用PrePersist Listener等待Person实体,但我不知道如何取消持久化(也许这是不可能的)。 我有以下代码:

public function prePersist(LifecycleEventArgs $args) {

  $entity = $args->getEntity();

  if($entity instanceof Personne) {

    $em = $args->getEntityManager();
    $persons = $em->getRepository('MyBundle:Person')->findBy(array(
      // unique fields          
    ));

    if(count($persons) > 0) {
      // ... ???
    }

}

我已尝试过$ em->分离,但由于我已经持有该实体,因此无用。

我想要的只是一种“获取或创造”。我解释一下,只有两种情况:

  • Person实体(非持久化)具有与数据库中存在的所有相同的字段(除了id字段),因此Person实体是数据库中的实体。我必须用数据库中的那个“替换”它;
  • Person实体(非持久化)在数据库中是唯一的,因此我们创建一个新实体(持久化)。

1 个答案:

答案 0 :(得分:1)

创建自己的 getOrCreate()方法并在侦听器中调用它。 请参阅此帖子Symfony2 doctrine FindOneOrCreate

另一种可能性是数据变换器。 http://symfony.com/doc/current/cookbook/form/data_transformers.html