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")