В schema.yml symfony/doctrine, где я должен поставить 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?


person nselikoff    schedule 28.09.2009    source источник


Ответы (3)


После долгих проб и ошибок единственный способ заставить его работать - это следовать предложению в комментарии Jestep и переместить определения отношений, включая onDelete: CASCADE, в таблицу связывания, поэтому в итоге это выглядит так и ведет себя как Я хочу, чтобы (удаляет каскад из Order в 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 Many-to-Many в Интернете, каждый из которых имеет отношения в немного разных местах. Разочаровывающий опыт.

person nselikoff    schedule 28.05.2010

Я почти всегда использую Propel, но по сути он должен быть таким же. Использование: при удалении: КАСКАД

Должно быть:

Order:
  columns:
    order_id: {...}
  relations:
    Upgrades:
      onDelete: CASCADE
      class: Upgrade
      local: order_id
      foreign: upgrade_id
      refClass: OrderUpgrade
person Jestep    schedule 28.09.2009
comment
Просто для подтверждения желаемого поведения: с этой спецификацией, если я удалю обновление, оно удалит связанные обновления OrderUpgrades, но не удалит ни одного Order? - person nselikoff; 28.09.2009
comment
На самом деле, после повторного просмотра onDelete: CASCADE должен быть в таблице Upgrade, а не в таблице Orders. Однако, учитывая отношения m2m, это может вообще не сработать. Чего я не понимаю в этой настройке, так это почему бы вам не иметь таблицу Orders, таблицу Upgrades и не иметь OrderUpgrade с внешним ключом к другим 2. Я не вижу всей картины, но она, похоже, уменьшает сложность этого. - person Jestep; 29.09.2009
comment
Сначала я пробовал это, но не мог заставить работать Doctrine:build-model и Doctrine:build-sql, пока не определил отношения m2m в соответствии с этой страницей: doctrine-project.org/documentation/manual/1_0/en/ - person nselikoff; 29.09.2009
comment
+1 у меня работала конфигурация onDelete в SF 1.4. Спасибо. - person nortron; 16.02.2010

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

После простого теста я пришел к выводу, что вы должны определить отношения во всех трех объектах.
 – Выполнение этого только в двух объектах, к которым вы хотите присоединиться, работает хорошо, за исключением каскадной части.
 – Выполнение этого только в объединении table (OrderUpgrade) работает, но вы не получите код формы и formfilter, сгенерированный в ваших 2-х объектах.
- Выполнение этого во всех 3-х объектах даст вам оба мира.

В следующем примере, который является подробным, но я предпочитаю, чтобы он был таким:
— если вы удаляете недвижимость, соответствующая запись PropertyLandlord удаляется, а запись Landlord остается нетронутой.
— если вы удаляете Landlord, то же самое вещь.
- и если вы удалите запись 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
person bksunday    schedule 01.09.2011
comment
Просто чтобы вы знали, если модель уже используется, и вы изменяете схему и надеетесь на создание-миграции-diff..., это может не сработать. - person bksunday; 01.09.2011
comment
хорошо, надеюсь, последний комментарий. Если вы используете миграцию, вам необходимо изменить сгенерированный код, который может пытаться удалить существующий внешний ключ и создать новые с добавленными числами, которые выглядят так же, как и раньше, за исключением каскадной части. как ни странно, повторно используйте одно и то же имя fk (без добавленной части) и, возможно, переместите создание в другой файл, и это сработает! - person bksunday; 01.09.2011