Это должен быть действительно простой материал, так как я не нашел обсуждения по этому поводу. Однако какое-то время я боролся с этим.
У меня довольно простое отношение «многие ко многим» с дополнительным полем, реализованным, например, в этот пример (двойное отношение "один ко многим"). Это хорошо работает при создании новых сущностей и сохранении их в базе данных. Сейчас я пытаюсь создать функцию редактирования и столкнулся с некоторыми проблемами.
Допустим, моя основная сущность называется Recipe, которая имеет отношение «многие ко многим» с сущностью Ingredient. Дополнительные поля, такие как «количество», находятся в объекте RecipeIngredient. Класс Recipe имеет метод setRecipeIngredient, который добавляет объект RecipeIngredient в массив ингредиентов.
Должен ли я создать некоторый метод «clearRecipeIngredients» для класса Recipe, который удалит все объекты RecipeIngredient? Я бы назвал это при редактировании рецепта, а затем создал новые объекты RecipeIngredient из моих данных и заполнил массив ингредиентов, как при создании нового объекта? Я признаю, что мои настройки каскада, вероятно, настроены неправильно, чтобы это работало, но я попытаюсь исправить это дальше.
Любые связанные примеры были бы замечательными.
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;
}
}
Примечание. Вам необходимо настроить каскадное сохранение и удаление потерянных файлов, чтобы этот код работал правильно.
Конечно, если вы выберете этот подход, ваш пользовательский интерфейс не должен отображать полную форму со всеми ингредиентами и количествами, которые можно редактировать одновременно. Вместо этого должны быть перечислены все ингредиенты с кнопкой «удалить» в каждой строке, а также кнопкой «изменить количество», которая, например, выводит всплывающую форму (с одним полем) для обновления количества.
Похожие вопросы
Связанные вопросы
Новые вопросы
doctrine-orm
Доктрина ORM - это PHP ORM. В то время как Doctrine 1.2 использует шаблон Active Record, Doctrine ORM 2 и выше использует шаблон Data Mapper. Проект Doctrine - это коллекция библиотек с открытым исходным кодом и инструментов для работы с абстракцией базы данных и объектно-реляционным отображением, написанных на PHP.