In the Doctrine manual, under Constrain relationships as much as possible, it gives the advice "Eliminate nonessential associations" and "avoid bidirectional associations if possible". I don't understand what criteria would make an association "essential".
I say this because it seems that you would often want to go from the One side of a One-to-Many association rather than from the Many side. For example, I would want to get all of a User's active PhoneNumbers, rather than get all active PhoneNumbers and their associated User. This becomes more important when you have to traverse multiple One-to-Many relations, e.g. if you wanted to see all Users with a MissedCall from the last two days (MissedCall->PhoneNumber->User).
This is how the simple case would look with an inverse association:
SELECT * FROM User u
LEFT JOIN u.PhoneNumbers p WITH p.active
It would make it more sensible if there were a way to go across a given relation in the opposite direction in DQL, like the following raw SQL:
SELECT * FROM User u
LEFT JOIN PhoneNumber p ON p.User_id = u.id AND p.active
Can someone explain why they give this advice, and in what cases it would be worth ignoring?
-- Edit --
If there are mitigating factors or other workarounds, please give me simple example code or a link.
I do not see any way to traverse a relation's inverse when that inverse is not defined, so I'm going to assume that building custom DQL is not in fact a solution -- there are some joins that are trivial with SQL that are impossible with DQL, and hydration probably wouldn't work anyway. This is why I don't understand why adding inverse relations is a bad idea.
Using Doctrine, I only define relationships when they're needed. This means that all of the relationships defined are actually used in the codebase.
For projects with a large team working on different areas of the project, not everyone will be accustomed to Doctrine, it's current configuration, and eager/lazy loading relationships. If you define bi-directional relationships where they aren't essential and possibly don't make sense, it could potentially lead to extra queries for data that:
Defining only essential relationships will allow you greater control over how you and your team traverse through your data and reduce extra or overly large queries
By essential relationships, I mean the ones you use. It doesn't make sense to define a relationship you wouldn't use. For example:
\Entity\Post
has a defined relationship to both \Entity\User
and \Entity\Comment
$post->user
to get author$post->comments
to get all comments\Entity\User
has a defined relationship to both \Entity\Post
and \Entity\Comment
$user->posts
to get all user posts$user->comments
to get all user comments\Entity\Comment
only has a relationship to \Entity\User
$comment->user
to get author$comment->post
as I don't retrieve the post it belongs to in my application
I wouldn't think of them as "Inverse" relationships. Think of them as "Bi-directional", if using the data in both directions makes sense. If it doesn't make sense, or you wouldn't use the data that way around, don't define it.
I hope this makes sense
I think this is a great question, and am looking forward to others' answers.
Generally, I've interpreted the advice you cited in the down to the following rule of thumb:
If I don't need to access the (inverse) association inside my entity, then I typically make it unidirectional. In your example of users and (missed) calls, I'd probably keep it unidirectional, and let some service class or repository handle putting together custom DQL for the odd occurrence when I needed to get a list of all users with recent missed calls. That's a case I'd consider exceptional -- most of the time, I'm just interested in a particular user's calls, so the unidirectional relationship works (at least until I've got so many records that I feel the need to optimize).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With