Context
Imagine a set of proposals, where every user can vote up or down for a proposal.
So I have 2 models:
- A
Proposal
, - A
Vote
, related to aproposal
, auser
, and anopinion
(up or down).
Now I want to display all my proposals, including extra information for each proposal:
- How many upvotes ?
- How many downvotes ?
- Has the current user upvoted ?
- Has the current user downvoted ?
Issue
This is really easy to implement, but this implies 4 request per proposal display (called the n+1 query issue). I come from Rails world, where this can easily be resolved using eager loading or some tricky queries. But I can not resolve it with doctrine and need some help!
What I tried
Use magical fields
The first solution is to make a custom query: select all the proposal, including the number of upvotes, downvotes, has the current user upvoted or downvoted.
The query now returns 4 more columns than the model describe: count_upvotes
, count_downvotes
, has_user_upvoted
and has_user_downvoted
.
To be useable with doctrine, I have to add these field to my Proposal
Entity.
For me, this is not a good solution, because it implies to always use this query to avoid bastard model, where these fields can be null.
Use a summary
The second solution is to make another object to be used by the view. This object is created with an argument: the current user. This object is created by optimized queries, and contains these methods:
getAllProposals()
getUpvotes($a_proposal)
getDownvotes($a_proposal)
hasUserUpvoted($a_proposal)
hasUserDownvoted($a_proposal)
For me, it's really overkilled to be forced to create an object just for a view optimization.
Use extended Entity
This third solution use an unique query to get proposals, their upvotes, downvotes, and check if user has up or downvoted.
It creates a new "extended" entity,
public function __construct(
Proposal $badgeProposal,
$upvotesCount,
$downvotesCount,
$hasUserUpvoted,
$hasUserDownvoted
) {
For me, this is the better solution, but for the moment this can not work because I don't know how to simply hydrate a Proposal from a SQL row (but I'm searching hardly).
Your turn
So, what can be other solutions? Is has to be a well-known issue for doctrine developers.