Где в symfony/doctrine's schema.yml я должен поставить OnDelete: CASCADE для отношений "многие ко многим"?
У меня есть отношения многие ко многим, определенные в моем проекте Symfony (с использованием доктрины) между Orders
а также Upgrades
(Order
может быть связано с нулем или более Upgrades
и Upgrade
может применяться к нулю или более Orders
).
# schema.yml
Order:
columns:
order_id: {...}
relations:
Upgrades:
class: Upgrade
local: order_id
foreign: upgrade_id
refClass: OrderUpgrade
Upgrade:
columns:
upgrade_id: {...}
relations:
Orders:
class: Order
local: upgrade_id
foreign: order_id
refClass: OrderUpgrade
OrderUpgrade:
columns:
order_id: {...}
upgrade_id: {...}
Я хочу настроить каскадное поведение, чтобы при удалении Order
или Upgrade
, все связанные OrderUpgrades
удалены. Куда я положу onDelete: CASCADE
? Обычно я ставлю это в конце раздела отношений, но в данном случае это может означать, что удаление Orders
будет каскадом удалить Upgrades
, Является ли Symfony + Doctrine достаточно умным, чтобы знать, чего я хочу, если я поставлю onDelete: CASCADE
в приведенных выше разделах отношений schema.yml?
3 ответа
После долгих проб и ошибок единственный способ, которым я смог заставить его работать, состоял в том, чтобы следовать предложению в комментарии Джестепа и перенести определения отношений, включая onDelete: CASCADE, в таблицу ссылок, так что в итоге это выглядит так и ведет себя как Я хочу это (удаляет каскад из Order to OrderUpgrade и из Upgrade в OrderUpgrade):
# schema.yml
Order:
columns:
order_id: {...}
Upgrade:
columns:
upgrade_id: {...}
OrderUpgrade:
columns:
order_id: { type: integer, notnull: true, primary: true }
upgrade_id: { type: integer, notnull: true, primary: true }
relations:
Order:
onDelete: CASCADE
Upgrade:
onDelete: CASCADE
Я должен сказать, что я немного ошеломлен всеми различными примерами YML Doctrine "многие ко многим" в Интернете, каждый из которых имеет отношения в немного разных местах. Расстраивающий опыт.
Мне надоело гуглить по этому поводу каждый раз, когда мне нужно каскадировать отношения между многими и многими и находить неполные ответы, так что вот мое мнение, которое на данный момент является наиболее полным из доступных.
После простого теста я пришел к выводу, что вы должны определить отношения во всех трех объектах.
- Выполнение этого только в двух объектах, к которым вы хотите присоединиться, работает хорошо, за исключением каскадной части.
- Выполнение этого только в таблице соединений (OrderUpgrade) работает, но вы не получите код формы и фильтра форм, сгенерированный в ваших 2 сущностях.
- Выполнение этого во всех трех сущностях даст вам оба мира.
В следующем примере, который является многословным, но я предпочитаю это так:
- если вы удалите Свойство, соответствующая запись PropertyLandlord будет удалена, а запись об Арендодателе останется нетронутой.
- если вы удалите Арендодателя, то же самое.
- и если вы удаляете запись PropertyLandlord, она только удаляет запись ссылки и оставляет нетронутой, что, я думаю, является поведением, которое мы в основном ищем.
Property:
columns:
id:
type: integer(8)
primary: true
autoincrement: true
title:
type: string(255)
notnull: true
relations:
Landlords:
class: Landlord
local: property_id
foreign: landlord_id
refClass: PropertyLandlord
Landlord:
columns:
id:
type: integer(8)
primary: true
autoincrement: true
title:
type: string(255)
notnull: true
relations:
Properties:
class: Property
local: landlord_id
foreign: property_id
refClass: PropertyLandlord
onDelete: CASCADE
PropertyLandlord:
columns:
property_id:
type: integer(8)
primary: true
notnull: true
landlord_id:
type: integer(8)
primary: true
notnull: true
relations:
Property:
local: property_id
foreign: id
class: Property
onDelete: CASCADE
Landlord:
local: landlord_id
foreign: id
class: Landlord
onDelete: CASCADE
Я почти всегда использую Propel, но он должен быть практически одинаковым. Использование: onDelete: CASCADE
Должно быть:
Order:
columns:
order_id: {...}
relations:
Upgrades:
onDelete: CASCADE
class: Upgrade
local: order_id
foreign: upgrade_id
refClass: OrderUpgrade