Fix N+1 Queries0:00
Okay, let's go ahead and work on pagination for comments. So I have 150 comments for this idea. And if I reload the page, you'll see that it takes quite a while to load. So if you look at the bug bar down here, you'll see it takes about 1.9 seconds, and we have 160 queries and 310 models. So I think we do have an N plus one issue here. So if we go to idea comments, you'll see that we are grabbing the comments from the idea, but I'm not eager loading the users for the comments. So if I just do load user, that should take care of the N plus one issue. So take a look at queries and models, 160, 310, down to 11 and 165.
Add Comments Pagination0:34
So if I just do load User, that should take care of the N plus one issue. So take a look at queries and models, 160, 310, down to 11 and 165. Okay. But it still takes quite a while to load at 1.75 seconds. So let's go ahead and add pagination. So instead of grabbing the comments, we are going to paginate them. So say paginate, and there's no pagination on collections. So we have to make sure to grab it on the query builder. So we can just do it like this. Okay.
Render Pagination Links1:10
So we can just do it like this. Okay. Let's go ahead and go to the view. So Idea comments and add the links here. So let's see if I put it in here, will it work? So let's say MY8 and let's do comments, links like this, comments, links. Okay. And let's make sure to use Livewire's pagination here. So we can just use withPagination as a trait here. So let's say use withPagination.
So we can just use WithPagination as a trait here. So let's say use WithPagination. Okay. So let's see if it paginates now. Okay. And if I scroll down, you see that we do have pagination here. So let's try to optimize this. As you see, we do have some time savings. Now it's 801 milliseconds and the pagination does work. Okay.
Optimize Comment Count Query2:02
Now it's 801 milliseconds and the pagination does work. Okay. But I think we can have some more savings here. If you remember for the comment count here. So that should be in IdeaController show. So where is it? comments right here. So again, we're loading in all the comments here, but now let's just grab it from the query builder and that should optimize some of our models at least. So we have 190 and now we're down to 40.
query builder and that should optimize some of our models at least. So we have 190 and now we're down to 40. Okay. And also down to 200 milliseconds. So that helped a lot actually. And we're still getting the correct result here. Okay. This down here, it's too long. So back to our Idea Comments, we can use the onEachSide method to shorten the amount of links that show.
So back to our Idea Comments, we can use the onEachSide method to shorten the amount of links that show. So let's just say one and this should be shorter now. And it is by just one or two. And I'm okay with that for now. But we are getting this line and I do want it to end here. So let's put that outside. So let's take this, cut it and let's put it outside of this container and let's make sure to put a marginLeft as well. So marginLeft 22.
to put a margin left as well. So marginLeft 22. So after this, let's go ahead and add this and let's add marginLeft 22, mediumMarginLeft 22. And the line should not show here anymore. Okay. So that's better. We can also specify the amount of results we want. So we can do that directly using the paginate method. So for Idea Comments, we can add a number in here and that's what I did for the ideas.
So we can do that directly using the paginate method. So for Idea Comments, we can add a number in here and that's what I did for the ideas. But I put it as a constant on the Idea model, but you can actually do it by just overriding a property on the model itself. So if you go into comments this time, and if you go into the actual model, you'll see that there is this perPage property that we can override. So let's grab this. Let's put it down here and let's say, say 5 to see if it works for now. Okay. And we do get 5 results per page, 1, 2, 3, 4, 5.
Okay. And we do get five results per page, one, two, three, four, five. So that does work. Let's put it to 20. Okay. And I'm also going to add the withQueryString method here. It's not needed. So this just makes sure that if we have any other query strings, that it keeps them in place when we use pagination. Okay.
Jump to Last Page5:40
The correct comment was on the last page or is on the last page. There it is. So we have to make sure to go to the last page before we scroll to that last comment. So we can actually make use of a method here on the Paginator instance called lastPage. And that's why I'm using normal pagination and not simple pagination, because I want to use this lastPage method. So let's go ahead and try using that. So in our Idea comments, we have this listener that listens for when a comment was added. Let's go ahead and go to the last page here. So after we refresh the Idea, let's go ahead and use this.
Let's go ahead and go to the last page here. So after we refresh the Idea, let's go ahead and use this. And there's also a goToPage method. Where is it? Up here somewhere. goToPage. Actually I believe that's on the Livewire trait. Where is it? Here. goToPage.
Here. Go to page. Yeah, there it is. So let's make use of that. So this go to page, and then we'll grab the last page. So this Idea, we have to grab the paginator instance, so we have to do the same thing. create, and then lastPage. Okay. So let's see if this works now. Save that.
So let's see if this works now. Save that. See if it goes to the last page when we add a new Comment. So let's scroll up again, let's refresh. Last Comment, okay. Idea comments does not exist. Sorry. Idea comments is what I meant. And this should not be a method. Okay.
And this should not be a method. Okay. Let's try that again. Refresh. Adding last comment, postComment. And it looks like it does go to the last page. Actually, no, I was on the last page. So let's try that again. Page two, scroll up. Does it go to last page comment?
Scroll on Page Change8:08
three or pressing the next button, as you can see, it doesn't scroll back to the top, it just kind of stays in place. But let's see if we can scroll it to the first comment. So back to our Idea or AddIdea component, sorry, AddComment. Let's see if we can work with this. So again, let's console.log the message and see if we have some information we can make use of in here. So console.log message. And let's take a look. Open up DevTools.
And let's take a look. Open up DevTools. And let's see what happens when we use pagination here. Okay, let's open that up. Let's check the updateQueue. And let's check something in here called method. And you can see we went to a certain page, I clicked on a certain page. But we also have options for nextPage or previousPage. So if I just hit the button instead, you'll see that. So again, this updateQueue, first one.
So if I just hit the button instead, you'll see that. So again, this updateQueue, first one. And we have this next page. And there's one for previous page as well. So let's see if we can listen for that and scroll to the first comment. So it's pretty similar to what we have here already. So let's make another case here. So if so, like I said, we have three cases. So it's if message.updateQueue. And it's the first one.
So it's if message.update queue. And it's the first one. And it's called method. So if it's equal to one of those three cases. So either go to page or let's grab this again. Next case is nextPage like this. And the last case is previousPage. Okay. And we'll clean this up in a second. Then we can do the same thing here, but just scroll to the first comment.
And we'll clean this up in a second. Then we can do the same thing here, but just scroll to the first comment. So let's grab this code to scroll. And it's a first comment. And it's a first child. And that should work, hopefully. Okay. So let's give that a try. Let's hide this. Let's refresh.
Let's hide this. Let's refresh. And now as I use pagination, it should scroll back to the first comment. So let's go to the first page. Scroll to the first comment. Okay. Let's try using the buttons here. So there should be page two. And that doesn't seem to work. That's because I have a typo here.
That's the first comment on page three. And the same for previous. So I should go back to page two and scroll to the top. And it does. Cool. So we can clean this code up a bit. We can just make use of the includes method here. So let me just comment this out and make a new one. So if... Let's make an array here of the possible values.
So if... Let's make an array here of the possible values. So the three values are goToPage, previousPage, and nextPage. So if this is included, so includes, and we can do message.updateQueue, zero method. Okay. And let's make sure to open that brace. Hopefully I did that right. And it should still work the same. So let's hard refresh. Let's try those three cases again.
So let's hard refresh. Let's try those three cases again. So let's try just going to a random page. Okay. Let's try next page. Okay. And let's try previous page. So it does work. Let's make sure that adding a comment still works as before. Adding a new comment should scroll to the last page and highlight it.
Refactor Ideas Pagination12:20
Let's make sure that adding a Comment still works as before. Adding a new Comment should scroll to the last page and highlight it. And it does. Cool. Pagination works, it scrolls, and everything seems to be working. So I'm just going to do some quick cleanup for our pagination for Ideas. So for our ideas index, we have pagination here. And like I said, I was using this constant, which we don't need, because we can add it directly on the Idea and override the perPage property. So let's say protected $perPage, like we did for the comments, and say 10 here, okay?
directly on the Idea and override the perPage property. So let's say protected perPage, like we did for the Comments, and say 10 here, okay? And then we don't need this, and then we don't need to add it in here. Okay. So let's make sure that still works for ideas should. So we should have 10, and it looks like it does work. I'm also going to add withQueryString here as well. So withQueryString, and then I'm going to get rid of where is it? ideas.index, the links here. Yeah.
And then let's try pagination here. Cool. So if I run the tests, I believe I was using that constant in one of my tests, so it might fail. So, yeah, it does fail for this test here. ShowIdeasTest. Okay. Let's go to that and fix it. ShowIdeasTest. Let's look for pagination.
Show Idea test. Let's look for pagination. So it's this test right here. And I'm just going to paste in an updated version here, which is also simpler. So we have one Idea. Instead of grabbing it from the constant, we're grabbing it from the method here, which just returns the value of perPage. So in this case, 10. And then we're just checking if these ideas. So we have 11 here.
Cool. And if the number of comments is less than the pagination count, then it should not even show that pagination. And you can see it doesn't show here, and everything should still work normally. Let's try again. And it does. Cool. So as always, let's make a commit here. So this is episode 51, git add, git commit, episode 51, comments, pagination. Okay, I'm back because I discovered that we still have an n+1 issue here.
Fix Remaining N+115:23
So this is episode 51, git add, git commit, episode 51, comments, pagination. Okay, I'm back because I discovered that we still have an n plus one issue here. So if you take a look at the queries and models on this show page, we have 32 and 50. And if you take a look at the request time, it's around 220. So if I refresh a few times, you'll see that it's around 220. Okay, so keep that in mind as our benchmark. So earlier in the video, we lazy eager loaded the User when we were still using a collection like this. So we did loadUser, and that helped fix the n plus one issue before we did pagination. So it was like this.
So we did load User, and that helped fix the n plus one issue before we did pagination. So it was like this. But unfortunately, that doesn't work on the query builder with what we have here. So if we try doing load User, that will not work. So if you go here, you'll see that we get an error. So to fix this, we can just grab the comments directly using Eloquent like this. And we can say Comment::where(idea_id, $ideaId). And we can still paginate and use this with queryString method. So actually, let me put this back. And let's see again.
So actually, let me put this back. And let's see again. So 3250, right? Actually, let's get rid of this load. Okay, and it was 3250 and around 220. So this should be pretty much the same without the eager load. So let's try that out. It still should be 3250. And it is, and it's still around 220 milliseconds. But now we can eager load the users here.
And it is, and it's still around 220 milliseconds. But now we can eager load the users here. So in each one of these, so if you're curious as to what queries are being run, if we open up the queries tab, you'll see that we have a new query for each of the users that made a comment. So if we eager load the users, so to do that, we can just do comment with user, then you'll see that it will fix that n plus one issue. So let's try this out. And keep an eye on the queries and models. And we are now down to 13 and 35.
And keep an eye on the queries and models. And we are now down to 13 and 35. And if I keep refreshing, you'll see that the refresh time is lower as well. So we have something around 200 or less, as opposed to 220. So yeah, just a quick note, I'll make sure to add this in the final code.
