Playing
01. Counting collection items vs aggregates

Transcript

00:00
In this series, we are looking at aggregates in Laravel. If you've ever displayed the count of a relationship inside of your app,
00:08
which is highly likely, then you've probably used a method like count on your models or your model relationships. For example, if a user had many articles, we know that articles like this as a property will return a Laravel collection.
00:25
Laravel's collection has a count method on it, which will count how many items are in that collection. So to get the count of articles, we would use user articles count,
00:35
and we'd either do this in code or we would do this directly in our templates. Now, this is okay, but there is a better way if you are displaying lots of counts for lots of different things, and you don't want to perform any additional queries.
00:49
For example, if you had a user on a page and you just wanted to show how many articles that they had, you don't need to actually grab that collection into memory to be able to count it. You can actually count at the database level,
01:01
and that's the key here. So we're going to spend the series looking at all of the different ways that we can work with aggregates, so you've got a really solid way to work with these,
01:11
and you'll be able to use them straight away in your projects. Okay, so we're going to spend a little bit of time setting up here. Now, I've gone ahead and created out a fresh Laravel project, and I've gone ahead and switched over my database credentials.
01:26
That is pretty much it. So the first thing that we're going to do is just go ahead and run our default migrations. That's going to create our users table and everything else we need, and we can start to go ahead and create a model for this user like we just looked at.
01:39
So let's go ahead and say PHP artisan make model, and let's create an article model out here. We'll create a migration alongside of this, and we can create a factory as well if we want to
01:50
generate some fake articles which we probably do. Okay, so let's head over to the articles migration and just quickly fill this in. So we're going to go ahead and relate this to a user of course. So we'll just use foreign ID here,
02:04
user ID, and we'll go ahead and use constraint to constrain that in the database. Also, we'll just include a title. So we'll just do this for now. That's going to be a string,
02:15
and I think that's just about enough information. We don't really care about what's in here, we just want to be able to count on it. So let's go ahead and say PHP artisan migrate, and we're done.
02:25
Okay, so the article factory just to generate out some fake records here. Let's go ahead and set the title in here using faker, and we'll just use sentence, and let's go ahead and just do this at five words, that's fine.
02:39
Okay, so over to the terminal, let's run PHP artisan and tinker, and let's go ahead and say app models and article. Grab the factory instance,
02:49
and let's generate this out say 100 times, and go ahead and create 100 articles. Okay, of course, we actually need to pass the user in. So let's create a fake user out first of all.
03:00
So user factory, and we'll just create this out on its own. So that's going to give us a fake user just here. Great. Okay, so now we can run this,
03:10
but we can pass the user ID in, not necessarily recommended, but we'll go ahead and do this anyway. So we'll set the user ID to one,
03:18
and there we go. Great. Okay, so we've got a fake user with a load of fake articles.
03:24
Let's just check the database out just to make sure. So there we go. All attached to user one. So we're just going to be playing around in here
03:32
under routes and web. We're not going to necessarily create much out here, but we are going to create out a view. Now I'm just going to use the default welcome view
03:41
that we get with Laravel. So let's clear this out, and then let's head back over to here and return that welcome view again.
03:49
And let's go ahead and grab that user. So we're just going to fetch this directly from the database by looking up by the ID. We are going to look later at how we do this
03:58
if we get the user passed in, maybe via route model binding. So let's go ahead and pull the user model in, and that's pretty much it.
04:06
Now, inside of the view, we want to pass the user down and then start to extract these counts out. So let's pass that user down,
04:14
and let's go ahead and set up the relationship for them articles so we can grab that count. So in the user's model, let's go ahead and create out an articles relationship,
04:24
and a user has many articles. So a very simple relationship article, and there we go. We're done.
04:32
Okay, so now under welcome.blade.php, we can go ahead and just output the user's name, maybe in an H1. So let's say user name,
04:41
and then down here, let's create an unordered list with some list items, and we'll say articles, and here is where we want the count.
04:49
So we would normally go ahead and say user articles and count, which we spoke about at the start of the video. Let's go over, give that a refresh, and there we go. There is the user, and there are the amount of articles.
05:02
Now, not only would we want to output the amount of articles, we would probably also want to pluralize this. So maybe we can just chop and change this around,
05:12
and go ahead and use string plural, parse in the singular version of this article, and then parse in the count. So let's head over and give this a refresh.
05:24
We get exactly the same result, but if the user only had one article, we would see one article written. So what we're doing here is grabbing a collection,
05:37
and we're going ahead and using the count method on it. Like I mentioned earlier, Laravel's collection has a count method. If we just open up the correct class here,
05:46
and have a look at that count method, you can see it would just use native count within PHP to grab the count for the items. So with this, what we're actually doing is wasting memory
05:59
by pulling in the articles collection, unless we actually want to iterate through them articles. So if this was a page where we did want to iterate through the articles,
06:09
it wouldn't necessarily be as bad going ahead and grabbing the collection. Now, just to kind of see what's going on here, we're going to go ahead and use Laravel debug bar,
06:19
specifically to monitor the memory usage of the page, but also to monitor how many queries we're running as well. So if we go down to install this, we'll get a better picture of what's happening in our app.
06:30
So let's go ahead and pull this in. Everything is done for you. So this will just now be available over in the browser. Okay, so we've got two queries here.
06:39
The first one is to fetch the user. That's pretty obvious because we looked them up by their ID. And the second is actually to grab all of the articles. So we're fetching every single article from this user,
06:52
just to then put it into a collection, and then just to go ahead and grab the count of it. Like I said, this query may be necessary if you actually want to iterate through the articles.
07:02
Now we've also got five meg of memory usage. Doesn't seem that high at the moment, but let's go ahead and now look at Laravel aggregates to see how these two things change.
07:13
First of all, the amount of queries we run, and second of all, the memory usage. So back to routes and web, let's take a look at what we can do here.
07:22
Now, what we do instead is we use with count. And what that's going to do is allow us to count out a certain relationships count. So let's go ahead and say articles and see what we get.
07:36
Now, if we head over to the browser here, nothing is going to change apart from the query that we are running. Now you can see here what we're doing is
07:44
when we do select this user by their ID, we're also creating a sub query here to select the count with that user ID in mind. So it's just basically counting out
07:57
all of the articles from that user. So this query is now redundant because we're actually getting the count of all of the articles.
08:03
Now let's go over and just die dump on this user model. And let's just take a look at this before we output it on the page. So if we look at our attributes here,
08:12
as well as all of the other attributes that we would expect for this user, we've also got this articles underscore count. This name is built up with Laravel by default,
08:22
we can change that and we're going to be looking at that later, but you can see, of course, we have a value of 100. So now rather than counting on that collection,
08:30
we've got a property attached to this model that we can use to just output this to the page. So let's go ahead and look at the difference. So remember over here, what we're doing at the moment,
08:38
we've got a five meg memory usage, two queries. Let's go over to the welcome.blade.php file. And instead of outputting the articles count from that collection, let's grab that property
08:51
on that model. So let's do that for here and let's do that for here. Let's go over, give that a refresh. So the first thing is we've not had to perform
09:00
an additional query to fetch this count or aggregate. We've done this aggregate directly when we look the user up. So we've saved one query.
09:09
What we've also done is saved about a megabyte, this is rough of memory usage, because we've not had to load all of them articles into a collection and then call the count method
09:20
on that collection. So hopefully this first episode has convinced you that Laravel aggregates can be really, really helpful in your apps.
09:29
What we're gonna do for the rest of the series is go through and look at all of the things around aggregates that we can do, including some more advanced things
09:37
and certain conditions for our aggregates. So you've got a, like I said at the start of the video, a really good foundation to work with aggregates and hopefully speed your apps up that little bit.
7 episodes 32 mins

Overview

If you're displaying counts in your app, instead of pulling records into a Collection to count on, try aggregates! Working at the database level, aggregates are performed in one query and lower the memory usage of your app. Let's explore everything you need to know to work effectively with aggregate data in Laravel.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!