Доктрина 2 сущности отношений Удалить
У меня есть собственная сущность, которая имеет следующее отношение к объекту "attribute":
/**
* @ORM\OneToMany(targetEntity="Attribute", mappedBy="entity", cascade={"persist", "remove", "merge"})
**/
protected $attributes;
Со стороны отношение принадлежащей сущности выглядит следующим образом:
/**
* @ORM\ManyToOne(targetEntity="Entity", inversedBy="attributes")
* @ORM\JoinColumn(name="entity_id", referencedColumnName="id")
*/
protected $entity;
Когда я создаю экземпляр объекта, добавляю ему атрибуты и сохраняю его. Все работает отлично.
Когда я удаляю один атрибут из объекта и сохраняю его, атрибут не удаляется в базе данных и повторно появляется при обновлении.
У кого-нибудь есть идея?
Ответы
Ответ 1
Решение
То, что вы ищете, это удаление сирот.
Вы можете прочитать, если вам нужны детали о том, почему ваша текущая ситуация не работает.
Каскадные проблемы
Каскадная операция не будет делать то, что вы хотите, к сожалению. "Cascade = [remove]" просто означает, что если объект сущности удален, то доктрина будет циклически проходить и удалять все дочерние атрибуты:
$em->remove($entity);
// doctrine will basically do the following automatically
foreach ($entity->getAttributes() as $attr)
{
$em->remove($attr);
}
Как это сделать вручную
Если вам нужно удалить атрибут из сущности, вы должны удалить атрибут следующим образом:
$entity->getAttributes()->removeElement($attr);
$em->remove($attribute);
Сведения о решении
Но для этого мы автоматически используем опцию удаления сирот. Мы просто говорим доктрине, что атрибуты могут принадлежать только сущности, и если атрибут больше не принадлежит сущности, просто удалите его:
/**
* @ORM\OneToMany(targetEntity="Attribute", mappedBy="entity", orphanRemoval=true, cascade={"persist", "remove", "merge"})
**/
protected $attributes;
Затем вы можете удалить атрибут, просто сделав следующее:
$entity->getAttributes()->removeElement($attr);
Ответ 2
Будьте осторожны при использовании сиротского удаления.
Если вы удалите элемент и затем вызовите обновление на основной сущности, элемент не будет удален из массива удаления дочерних сирот.
И если flush вызывается позже, это приведет к удалению этой записи из db, игнорируя обновление.
Это выглядит как ошибка для меня, и это привело к потере изображений для многих продуктов в моем приложении. Я должен был выполнить прослушиватель, чтобы вызывать повторную попытку на этих объектах после того, как они были запланированы для удаления.