用于一对多和一对一关系的 Doctrine yaml

发布于 2024-09-07 13:09:59 字数 1049 浏览 3 评论 0原文

我有两个对象:File 和 FileDetail。一个File可以有多个FileDetails,但一个FileDetail只能有一个File。我可以让它工作,但由于关键限制,我无法从数据库中删除任何内容(我无法删除 File 行,因为 FileDetail 依赖于它,反之亦然)。我有以下 yaml:

File:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    ...
    fileDetail_id: integer
  relations:
    ...
    FileDetail:
      local: fileDetail_id
      foreign: id
      cascade: [delete]

FileDetail:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    file_id: integer
    ...
  relations:
    ...
    File:
      local: file_id
      foreign: id
      foreignAlias: Revisions
      cascade: [delete]

理想情况下,当我删除 File 行时,所有子 FileDetails 也会被删除。如果我可以手动删除所有 FileDetail 行,然后删除 File 行,那就太好了,但由于关键限制,我无法:

1451 - Cannot delete or update a parent row: a foreign key constraint fails (`file`, CONSTRAINT `file_filedetail_id_file_detail_id` FOREIGN KEY (`filedetail_id`) REFERENCES `file_detail` (`id`))

如何让这种类型的关系发挥作用(一对多)一侧,但另一侧是一对一)。或者我应该将其视为双方的多对多?

I have two objects: File and FileDetail. A File can have many FileDetails, but a FileDetail can only have one File. I can get this to work, but I can't delete anything from the database because of key constraints (I can't delete the File row because FileDetail depends on it, and vice versa). I have the following yaml:

File:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    ...
    fileDetail_id: integer
  relations:
    ...
    FileDetail:
      local: fileDetail_id
      foreign: id
      cascade: [delete]

FileDetail:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    file_id: integer
    ...
  relations:
    ...
    File:
      local: file_id
      foreign: id
      foreignAlias: Revisions
      cascade: [delete]

Ideally what I would like to happen is when I delete the File row, that all the child FileDetails are deleted as well. It would even be nice if I could just manually delete all the FileDetail rows and then the File row, but because of the key constraints I'm unable to:

1451 - Cannot delete or update a parent row: a foreign key constraint fails (`file`, CONSTRAINT `file_filedetail_id_file_detail_id` FOREIGN KEY (`filedetail_id`) REFERENCES `file_detail` (`id`))

How would I get this type of relationship to work (One-To-Many on one side, but One-To-One on the other). Or should I just treat this as a Many-To-Many on both sides?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

纸短情长 2024-09-14 13:09:59

对于 Doctrine,通常最好只定义一侧(通常是拥有方)的关系,然后让 Doctrine 解决其余问题。在这里,您有一个级联删除,看起来是双向的。尝试将您的架构更改为:

File:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    ...
  relations:
    ...
    Revisions:
      class: FileDetail
      local: id
      foreign: file_id
      type: many
      cascade: [delete]

FileDetail:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    file_id: integer

并仅将 cascade 保留在文件端。这样,当您删除文件时,其关联的 FileDetail 记录也将被删除。我还根据您的原始架构将别名更改为 Revisions,因此您将能够执行以下操作:

$file->Revisions->{some FileDetail field here}

我认为这就是您所追求的。我已从您的文件记录中删除了 filedetail_id 字段,就好像每个文件可以有许多 FileDetail 记录一样,您的文件记录将无法将这些记录的所有 ID 存储在单个整数字段中。

最后,我在拥有方添加了 type: Many ,因此 Doctrine 知道这是来自 File 方的一对多关系。

With Doctrine, it can often be better to only define the relationship on one side (usually the owning side) and let Doctrine work out the rest. Here, you've got a cascading deletion which looks to be going both ways. Try altering your schema to:

File:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    ...
  relations:
    ...
    Revisions:
      class: FileDetail
      local: id
      foreign: file_id
      type: many
      cascade: [delete]

FileDetail:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    file_id: integer

and leave the cascade on the File side only. That way, when you delete a File, its associated FileDetail records will be deleted as well. I've also changed the alias to Revisions as per your original schema, so you'll be able to do:

$file->Revisions->{some FileDetail field here}

which I think is what you were after. I've removed the filedetail_id field from your File record as if you can have many FileDetail records per file, your File record would not be able to store all the IDs of those records in a single integer field.

And finally, I've added type: many to the owning side, so Doctrine knows that it's a one-to-many relationship from the File side.

メ斷腸人バ 2024-09-14 13:09:59

对 richsage 的答案的一个小补充:

如果您在非拥有方定义关系,Doctrine 可能会在检测此设置时遇到问题。

一个明显的症状是当您收到一条错误消息,指出在引用表中找不到外键列。
在这些情况下,您可以帮助 Doctrine 在关系中提供“owningSide”属性。以上面的例子为基础:

File:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    ...
  relations:
    ...
    Revisions:
      class: FileDetail
      local: id
      foreign: file_id
      type: many
      owningSide: false
      cascade: [delete]

A small addition to richsage's answer:

In case you're defining relation on the non-owning side, Doctrine might have problems detecting this setup.

A clear symptom for this is when you get an error message saying that the foreign key column is not found in the referencing table.
In these cases you can help out Doctrine providing the "owningSide" attribute in the relation. Taking the above example as a base:

File:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    ...
  relations:
    ...
    Revisions:
      class: FileDetail
      local: id
      foreign: file_id
      type: many
      owningSide: false
      cascade: [delete]
痞味浪人 2024-09-14 13:09:59

@richsage我对你的解决方案遇到的唯一问题是,对我来说,在FileDetail:定义中,file_id:必须有primary:true。

@richsage the only issue I had with your solution, is that for me, in the FileDetail: definition, the file_id: had to have primary: true.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文