Closed patricknelson closed 9 years ago
@patricknelson Have you tried using dot-notation?
<?php
class Contest extends DataObject {
private static $has_many = [
"GrandPrizeWinners" => "Person.GrandPrize",
"RunnersUp" => "Person.RunnerUp",
];
}
class Person extends DataObject {
private static $has_one = [
"GrandPrize" => "Contest",
"RunnerUp" => "Contest",
];
}
Great Scott! That's magic. Yes, it does work. Is that documented? Also, it was slightly harder to track down since apparently for it to work I had to perform a dev/build
and didn't realize it.
It is documented (though it’s pretty hard to spot at a glance!): http://doc.silverstripe.org/en/developer_guides/model/relations/#has-many
And all that time. :facepalm:
I'm so used to using methods to define relations (both in my own ORM and in Laravel's Eloquent) where you are guided on additional optional syntax, not realizing that these strings encoded into private static
variables have syntax that I overlooked which may (or may not) solve my problem. Anyway -- yet again, thanks for pointing me in the right direction and sorry for wasting your time! :D
Apparently,
DataObject->getRemoteJoinField()
has a flaw in it preventing you from having two separate relations from a parent to the same child object. It appears this may only affect the3.1
branch, since reviewing the newer code in the3
branch, I think this bug may have been addressed.For example, say you have a website with contests and you can have multiple grand prize winners but also have multiple runners up. Also, say you have these contests monthly and the same players will play. You can boil this down to the following:
It turns out that in
->getRemoteJoinField()
, which is responsible for automatically determining the foreign key (e.g. "GrandPrizeID" pointing back to theContest
object) usesarray_flip()
when it gets the names of the unique relations (on the child object,Person
) pointing back to the parent object (Contest
) and, in doing so, clobbers the first relation (GrandPrize
) which means that when you attempt to get the relation for->GrandPrizeWinners()
it will return aHasManyList
forRunnerUp
instead.Right now, it doesn't matter what the relation names are on the parent/child objects. However, due to the inability to determine which relation to use to reference back properly, e.g. that
GrandPrizeID
should be used for the->GrandPrizeWinners()
relation, it will matter what the relation name is, if you happen to have an edge case like mine where you need multiplehas_many
relations from the same parent to the same child (without usingmany_many
, which admittedly may be a workaround for this).My pull request #4093 will prefer the
has_one
relation pointing back that has a matching name in the parenthas_many
and, if no matching name is found, will continue with the existing functionality.