在 symfony/doctrine 的 schema.yml 中,我应该在哪里放置 onDelete: CASCADE 用于多对多关系?

Posted

技术标签:

【中文标题】在 symfony/doctrine 的 schema.yml 中,我应该在哪里放置 onDelete: CASCADE 用于多对多关系?【英文标题】:In symfony/doctrine's schema.yml, where should I put onDelete: CASCADE for a many-to-many relationship? 【发布时间】:2009-09-28 17:02:22 【问题描述】:

我在我的 Symfony(使用原则)项目中定义了 OrdersUpgrades 之间的多对多关系(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: ...

我想设置删除级联行为,这样如果我删除OrderUpgrade,所有相关的OrderUpgrades 都会被删除。我在哪里放onDelete: CASCADE?通常我会把它放在关系部分的末尾,但这似乎意味着在这种情况下删除Orders 会级联删除Upgrades。如果我将onDelete: CASCADE 放在 schema.yml 的上述关系部分中,Symfony + Doctrine 是否足够聪明,可以知道我想要什么?

【问题讨论】:

【参考方案1】:

经过多次试验和错误,我能够让它工作的唯一方法是按照 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

我必须说,我对互联网上所有不同的 Doctrine Many-to-Many YML 示例感到有些不知所措,每个示例的关系都略有不同。令人沮丧的经历。

【讨论】:

【参考方案2】:

我几乎总是使用 Propel,但它应该基本相同。使用:onDelete:级联

应该是:

Order:
  columns:
    order_id: ...
  relations:
    Upgrades:
      onDelete: CASCADE
      class: Upgrade
      local: order_id
      foreign: upgrade_id
      refClass: OrderUpgrade

【讨论】:

只是为了确认所需的行为:使用此规范,如果我删除升级,它将删除相关的订单升级,但不会删除任何订单? 其实onDelete: CASCADE应该在Upgrade表而不是Orders表,再看一遍。但是,鉴于 m2m 关系,这可能根本行不通。我对这个设置不理解的是,为什么你没有一个 Orders 表、一个 Upgrades 表并且没有 OrderUpgrade 和另一个 2 的外键。我看不到整个画面,但它似乎会减少这很复杂。 我起初尝试过,但无法让教义:构建模型和教义:构建sql工作,直到我根据此页面定义 m2m 关系:doctrine-project.org/documentation/manual/1_0/en/… +1 onDelete 配置在 SF 1.4 中对我有用。谢谢。【参考方案3】:

每次我需要级联多对多关系并找到不完整的答案时,我都厌倦了在谷歌上搜索它,所以这是我对它的看法,这是迄今为止最完整的。

经过一个简单的测试,我认为您应该定义所有 3 个实体中的关系。 - 仅在您想要加入的 2 个实体中执行此操作效果很好,但级联部分除外。 - 仅在连接表 (OrderUpgrade) 中执行此操作,但您不会获得在 2 个实体中生成的表单和表单过滤器代码。 - 在所有 3 个实体中执行此操作将为您带来两全其美。

在以下示例中,虽然很冗长,但我更喜欢这样: - 如果你删除一个Property,对应的PropertyLandlord条目被删除,而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

【讨论】:

只是让您知道,如果模型已经被使用并且您正在修改架构并希望生成-迁移-diff..这可能无法正常工作。 好的,希望最后一次自我评论。如果您确实使用迁移,则需要修改生成的代码,该代码可能会尝试删除现有外键并创建附加数字的新外键,除了级联部分外,这些数字看起来与以前相同。奇怪的是,重复使用相同的 fk 名称(不带附加部分),并可能将创建移动到另一个文件,并且它可以工作!

以上是关于在 symfony/doctrine 的 schema.yml 中,我应该在哪里放置 onDelete: CASCADE 用于多对多关系?的主要内容,如果未能解决你的问题,请参考以下文章

在 Symfony 中防止 Doctrine 的查询缓存

Symfony2/Doctrine 提交表单需要很长时间

Symfony/Doctrine 中的 SQL 注入

Symfony2 / Doctrine2:不要在模式上删除全文索引:更新

Symfony2\Doctrine - 检索用户角色

Symfony2 - Doctrine - 在实体管理器刷新调用中捕获错误