[5.7] Added loadCount method to eloquent collections#25997
[5.7] Added loadCount method to eloquent collections#25997taylorotwell merged 2 commits intolaravel:5.7from timacdonald:collection_load_counts
Conversation
|
Maybe add an integration test for this? There is so much mocking going on here that the test feels too brittle. |
| $query = $this->first()->newQueryWithoutRelationships() | ||
| ->whereKey($this->modelKeys()) | ||
| ->select($this->first()->getKeyName()) | ||
| ->withCount($relations); |
There was a problem hiding this comment.
You can use ->withCount(...func_get_args()) and remove line 72.
There was a problem hiding this comment.
Noice one, much nicer.
|
This doesn't work for me: You are using There can be issues with global scopes: class User extends Model {
use SoftDeletes;
}
$users = User::withTrashed()->get();
$users->loadCount(...); // Doesn't load soft-deleted models.Is there a specific reason for using |
|
@staudenmeir there was an ignorant reason, yes, but looking at it with fresh eyes...no, it doesn't give us any benefit chunking the results as they are all gonna stay in memory when we attach the counts to the existing models. I've updated that. Thanks for pointing that out. You are right about the @X-Coder264 I'll add some integration tests as well - all that mocking was freaking me out tbh! |
|
Integration tests added 💪 thanks for the feedback so far on this one. They cover soft deleted items and guarded attributes as mentioned. |
|
Should we also add a Of course, there is no performance advantage for a single model, but we also have $posts->comments_count = $post->comments()->count(); |
This PR introduces the ability to load relationship counts on an
Eloquent\Collection. With the query builder you can$query->with($relations)and also$query->withCount($relations), but on the eloquent collection we can only$collection->load($relations). This introduces the ability to$collection->loadCount($relations).Usually, of course, you would want to be loading these counts when you are retrieving the models from the DB in the first place, i.e. with the query builder as shown above, however in certain circumstances that is not possible. One example is when the model you are retrieving has a polymorphic relation on which you need to dynamically load counts based on the class type.
A real world example of how I would use this in my current app...
I am tracking certain events. An event is something like "Post created" or "Comment created". Each event has an
eventablerelation that is polymorphic, i.e. it might be aPostor aCommentOn my events endpoint, I want to show each event and some information about the eventable. The information shown for each eventable item can vary. For a
Postit might be the number of comments it has recieved and for aCommentit might be the number of hearts it has received.Show me the code!
Not sure if this was the best example of its use, but it is a real one. Hopefully it would be useful in other situations also.
Under the hood the query is havingeachcalled on it, causing the db hits to be chunked. Only the model primary key and relation counts are being retrieved from the DB to keep the payloads and memory impact as low as possible. It is defaulting the the 1000 chunk count.Some places where this idea has been discussed / requested:
If a few people could do a once over of the test I've introduced that would be awesome - not used to mocking soooo many things 😅
Also, if there is anyway to optimise the way I'm doing this, I'm all ears 👂