我有两个对象:File和FileDetail。文件可以有很多FileDetails,但FileDetail只能有一个文件。我可以让它工作,但由于关键的限制,我无法从数据库中删除任何内容(我无法删除文件行,因为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`))
我如何才能使这种关系发挥作用(一方面是一对多,另一方面是一对一)。或者我应该把它视为双方的多对多?
答案 0 :(得分:5)
使用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知道它是文件方面的一对多关系。
答案 1 :(得分:1)
富豪的回答:
如果您在非拥有方面定义关系,则Doctrine可能在检测此设置时遇到问题。
明显的症状是当您收到错误消息,指出在引用表中找不到外键列时。 在这些情况下,您可以帮助Doctrine提供"拥有Side"关系中的属性。以上面的例子为基础:
File:
columns:
id:
type: integer
primary: true
autoincrement: true
...
relations:
...
Revisions:
class: FileDetail
local: id
foreign: file_id
type: many
owningSide: false
cascade: [delete]
答案 2 :(得分:0)
@richsage我对你的解决方案唯一的问题是,对我来说,在FileDetail:定义中,file_id:必须有primary:true。