严格来说,正如你所提到的,这里没有多对多的关系,而是一对多之后是多对一的关系。
关于你的问题,每次我想编辑食谱时,我都不会执行批量“清除”操作。相反,如果您想编辑基于纸张的配方,我会提供一个流畅的界面来模仿将要采取的步骤。
我下面提供的实现:
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 persist和orphan removal此代码才能正常工作。
当然,如果您采取这种方法,您的用户界面不应该显示一次完整编辑所有成分和数量的完整表格。相反,应列出所有成分,每行上有一个“删除”按钮以及一个“更改数量”按钮,例如,该按钮将弹出一个(单字段)表单以更新数量。