Doctrine yaml for a One-To-Many And One-To-One Relationship
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?
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.
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]
@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.
精彩评论