嚴格來說,正如你所提到的,這裏沒有多對多的關係,而是一對多之後是多對一的關係。
關於你的問題,每次我想編輯食譜時,我都不會執行批量「清除」操作。相反,如果您想編輯基於紙張的配方,我會提供一個流暢的界面來模仿將要採取的步驟。
我下面提供的實現:
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此代碼才能正常工作。
當然,如果您採取這種方法,您的用戶界面不應該顯示一次完整編輯所有成分和數量的完整表格。相反,應列出所有成分,每行上有一個「刪除」按鈕以及一個「更改數量」按鈕,例如,該按鈕將彈出一個(單字段)表單以更新數量。