Доктрина 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, игнорируя обновление.

Это выглядит как ошибка для меня, и это привело к потере изображений для многих продуктов в моем приложении. Я должен был выполнить прослушиватель, чтобы вызывать повторную попытку на этих объектах после того, как они были запланированы для удаления.