更新doctrine2实体

时间:2011-12-21 07:54:58

标签: doctrine-orm

这一定是非常基本的东西,因为我没有找到任何关于它的讨论。不过我已经有一段时间了。

我与this example中实现的额外字段有很多基本的多对多关系(双一对多关系)。这在创建新实体并将其保存到数据库时很有效。我现在正在尝试创建编辑功能并遇到一些问题。

让我们说我的主要实体名为Recipe,它与Ingredient实体有多对多的关系。像“amount”这样的额外字段位于RecipeIngredient实体中。 Recipe类有setRecipeIngredient方法,它将RecipeIngredient对象添加到components数组。

我应该为Recipe类创建一些“clearRecipeIngredients”方法,这会删除所有RecipeIngredient对象吗?我会在编辑Recipe时调用它,然后从我的数据创建新的RecipeIngredient实体并填充成分数组,就像创建新实体一样?我承认我的级联设置可能没有正确设置,但我尝试下次修复它。

任何相关的例子都会很棒。

1 个答案:

答案 0 :(得分:1)

严格来说,正如你所提到的,这里没有多对多关系,但是一对多关系后跟多对一关系。

关于您的问题,每次我想编辑食谱时,我都不会批量“清除”。相反,我会提供一个流畅的界面来模仿你想要编辑基于纸张的食谱时所采取的步骤。

我在下面提供了一个示例实现:

class Recipe
{
  /**
   * @OneToMany(targetEntity="RecipeIngredient", mappedBy="recipe")
   */
  protected $recipeIngredients;

  public function addIngredient(Ingredient $ingredient, $quantity)
  {
    // check if the ingredient already exists
    // if it does, we'll just update the quantity
    $recipeIngredient = $this->findRecipeIngredient($ingredient);
    if ($recipeIngredient) {
      $quantity += $recipeIngredient->getQuantity();
      $recipeIngredient->updateQuantity($quantity);
    }
    else {
      $recipeIngredient = new RecipeIngredient($this, $ingredient, $quantity);
      $this->recipeIngredients[] = $recipeIngredient;
    }
  }

  public function removeIngredient(Ingredient $ingredient)
  {
    $recipeIngredient = $this->findRecipeIngredient($ingredient);
    if ($recipeIngredient) {
      $this->recipeIngredients->removeElement($recipeIngredient);
    }
  }

  public function updateIngredientQuantity(Ingredient $ingredient, $quantity)
  {
    $recipeIngredient = $this->findRecipeIngredient($ingredient);
    if ($recipeIngredient) {
      $recipeIngredient->updateQuantity($quantity);
    }
  }

  protected function findRecipeIngredient(Ingredient $ingredient)
  {
    foreach ($this->recipeIngredients as $recipeIngredient) {
      if ($recipeIngredient->getIngredient() === $ingredient) {
        return $recipeIngredient;
      }
    }
    return null;
  }
}

注意:您需要设置cascade persistorphan removal才能使此代码正常运行。

当然,如果采用这种方法,您的用户界面不应显示包含所有成分和数量的完整表单。相反,应列出所有成分,每行都有一个“删除”按钮,以及一个“更改数量”按钮,它会弹出一个(单一字段)表单来更新数量,例如。