Symfony2 и Doctrine: один-ко-многим с удалением сирот из таблицы соединений

У меня есть объект "AnnualReport", который принимает коллекцию объектов "AnnualReportStaffing". Годовой отчет состоит из четырех различных разделов "Кадровое обеспечение" и, следовательно, четырех из этих сборников (ArrayCollection). Поскольку я не могу использовать традиционные отношения "один ко многим", я должен использовать "один ко многим" с таблицей соединений, как описано здесь.

Так, например, одна из моих коллекций штатного расписания определена как таковая в моем классе AnnualReport:

/**
 * @ORM\ManyToMany(targetEntity="AnnualReportStaffing", cascade={"persist"}, orphanRemoval=true, fetch="LAZY")
 * @ORM\JoinTable(name="annualreports_staffingtenure",
 *      joinColumns={@ORM\JoinColumn(name="staffing_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="annualreport_id", referencedColumnName="id")},
 *      )
 */
private $staffing;

Теперь, когда приходит время удалять AnnualReport, Doctrine удаляет связь между отчетом и штатным расписанием в объединяющей таблице, но НЕ удаляет связанные сущности AnnualReportStaffing. Я попытался добавить cascade={"remove"}, но получаю нарушение внешнего ключа, поскольку он пытается удалить объект Staffing до того, как будет удалена ассоциация таблицы соединений.

Каков наилучший способ удалить осиротевшие кадры? Очевидно, что orphanRemoval=true не является ответом.

2 ответа

Решение состоит в том, что вы должны сначала отсоединить штатное расписание от ORM, чтобы оно больше не отслеживалось. После отсоединения его можно удалить без нарушения внешнего ключа. Кроме того, для удаления самого отчета в обратном столбце должно быть установлено onDelete="CASCADE". Я не уверен, что это самое безопасное или элегантное решение, но, похоже, оно подходит для этого конкретного случая использования.

/**
 * @ORM\ManyToMany(targetEntity="AnnualReportStaffing", cascade={"persist", "detach", "remove"}, orphanRemoval=true, fetch="LAZY")
 * @ORM\JoinTable(name="annualreports_staffingtenure",
 *      joinColumns={@ORM\JoinColumn(name="annualreport_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="staffing_id", referencedColumnName="id", onDelete="CASCADE")},
 *      )
 */

Вы можете попробовать вот так:

@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
Другие вопросы по тегам