This episode is for members only

Sign up to access "Laravel Performance" right now.

Get started
Already a member? Sign in to continue
Playing
11. Caching basics

Transcript

00:00
A really effective way to improve the speed of your apps is to utilize caching. Now caching is an incredibly complex topic and Laravel's caching functionality is very powerful.
00:12
But the majority of the time really we can just cache something, return it, show it in a view and we can pretty much leave it like that. I'm going to show you how to cache stuff in Laravel. We're going to talk about the different caching drivers that we can use
00:27
and we're also going to look at clearing the cache as well if you need to manually do this. So we're going to use the home page for this because effectively what we're going to end up here once we cache the data that we are retrieving from the database here are no database queries at all on the home page.
00:45
We're also then going to see the request duration go down even further than the 60 or 70 milliseconds that we already have. So first of all let's go over to our env file and you can see here that we've got an option to set our cache driver.
01:01
Now if we open up config and cache what we'll actually find in here is a list if we head down to this cache store section, a list of all of the supported drivers within Laravel. Now we're going to go ahead and switch this over to file based caching
01:17
just to demonstrate this in this episode. But I would recommend using something like Redis or Memcached. It really depends on your use case and what you have available. So we've got our cache driver currently set to file.
01:30
If it's set to null nothing will be cached. That's a perfectly acceptable cache store to use if you are testing things locally. But we're going to leave this as file just for now. Okay so how do we cache stuff?
01:41
Well let's go over to our home controller and just play around with this here. In Laravel we have a cache helper here which we can use or you can use the cache facade it's entirely up to you. So we're going to go ahead and use this cache helper and we're going to say remember
01:56
and into this we're going to pass in a key. So everything that you store in a cache is going to be stored under a key so you can later retrieve it. So what we're going to do is just say test here.
02:07
We're then going to pass in the amount of time that we want this cached for. So in our case let's go ahead and choose one hour. This value is in minutes. So if you want to cache for one minute you would pass one in.
02:18
If you want to cache for an hour you would choose 60. And just a tip here if you want this cache for a certain amount of hours a good idea is just to multiply this by the number of hours that you want. It just makes it a little bit easier to read for yourself in the future and other developers.
02:34
So I'm just going to cache this for one hour and the third argument here is going to be a closure. From this we return the value that we want to be cached. So what's actually going to happen here? What's the life cycle of this cache?
02:47
Well what's going to happen is the first time we call this we're going to resolve this value out of the callback. So this is just going to be returned to us. The second time we do this Laravel will pluck this value out of the cache that we've chosen.
03:00
In our case all of this data is being stored in a file and it will pluck this out by the key that we have given. Now for a string value of course this doesn't make any sense whatsoever but when we get two database calls which we're going to do down here in a second
03:13
that makes a lot of sense. That means that the first time someone lands on your app it makes a call to the database to grab that data if the cache has expired after an hour and then the second time around this will be pulled directly from the cache
03:25
which means we don't need to make any database queries. So let's go ahead and just die dump on this test value and we're not really going to see any difference here because when I refresh this it doesn't really show us any queries
03:36
or the fact we're not running queries but this value is actually now being pulled out of the cache. Now we can kind of prove this by changing the value of the return value inside of here. So I'm just going to change this to testing
03:50
and if we just give this a refresh you can see it still shows test. That is because the value previously was cache. This data has been updated but we're returning the cache data under the test key. We have an expiry for an hour
04:04
so if I were to walk away for an hour and come back later and give this a refresh then this would then pull out the new value and that would be cached for an hour. So that's the very basics of caching. So we are now going to apply what we have here to the query that we've created here.
04:22
Now we need to be really really careful here because first of all if we are caching data that is regularly updated for example if you had a list of posts and you maybe see three or four posts come in every hour and you cache this for an hour
04:35
you're going to have a delay on the data that you get shown. So really it's just something you need to tweak around to get the benefit of seeing that data but also having the speed of when this is cached. What we also need to be careful about is things like pagination
04:50
and also the things like this where we're passing in a user id. We don't want all of this data to be cached under a particular user. That would mean that when someone comes in and chooses a different user to show the different users posts it's going to return the wrong data.
05:06
Now I'll demonstrate that but what we're going to do is just simplify this really quickly and then take a look at that more complex caching scenario. So I'm going to go ahead and repaste this up here. I'm just going to comment out all of what we've done down here
05:18
and we're going to simplify this by just changing this to get and let's add a limit on here just so we don't have too much data. So let's limit this by let's say 50 or 100 and we're going to go ahead and remove the when just in here.
05:34
So this is very plain data there's no control from the user here. There's no pagination so we can't paginate this and we just see the list of posts. So let's go over to the browser give this a refresh and yeah we just need to update our home.blade.php file to get rid of these links.
05:52
So let's just get rid of this really quickly and there we go great. Okay so we can see here we've got a query with a around about 80 70 80 request duration. Okay let's cache this so back over to the home controller. We're going to go ahead and say cache remember we're going to choose a key.
06:11
So let's just say this is home.posts because you might have posts elsewhere. It doesn't really matter what you call these keys as long as you're consistent. We're going to cache these for an hour and we're going to create our closure just in here and then we're going to assign the value the return value of this to posts because
06:27
we will get all of these posts returned into here like we saw with that example earlier with the string. So I'm going to cut this out of here and I'm going to return from here the result of the query that we get and that is pretty much all we need to do. Now if we head over and just give this a refresh like I said the first request this data has been pulled from the database it's now being
06:47
cached under this home.posts key for an hour and then when we refresh again notice that we don't see any queries. We're still seeing the same data here but this is now being pulled from the cache that is why we don't have any database queries here and that is why our request duration has gone down from about 70 or 80 milliseconds to about 30 or 40. Let's take a look at clearing
07:09
the cache manually. You can do this from code or you can do this from the artisan command line. I'll show you how to do both. So we're going to go over to our command line and we're going to run php artisan cache and clear. What that's going to do is it's going to clear out all of the application cache data so when we refresh this we're back to the point where now we're making a database request
07:30
that's going to be recached again. So if you ever need to force clear everything out you can go ahead and do that. It's not recommended to clear your entire cache necessarily because that's going to have an immediate impact on your page load time if you have a lot of data that you're caching. Now you can also do this from code so let's just demonstrate this up here by saying cache and
07:50
forget and we're going to go ahead and forget home.post. So if anywhere in your code something changes like a published article goes live and you want to clear out all of the home post cache so that new article can appear within that cache you can do that somewhere in here. So if we come over and just give this a refresh you can see sure enough this just is never getting cached because
08:11
we're always clearing the cache out before we hit this page and before the user sees that page. These are good to put in things like observers within your models so when something goes live for example or even when a record is created you can just flush out the cache. I think we'll take a look at that in the next episode because that's a really important concept. For now though let's
08:31
go back to the issue that we spoke about earlier where we could potentially have data from the query string. So I'm actually going to take all of what we commented out I'm going to take this and put this inside of our closure just here so we're going to return all of that and just go ahead and indent that. So let's get rid of that assignment and what this is doing now if we just bring the request
08:54
into scope it is caching this based on the first user that would have been selected. So let me show you how this works. So the first thing I'm going to do is just go ahead and clear the cache out we're going to come over here and we're going to say user id equals three. We get a list of articles here and sure enough they are now cached but when we go back to user id of one this data
09:14
remains the same because the first hit to this and the first cache store stored the articles for user three so now we can't access anything else. This is where we need to get creative with the cache key and include information like this as well as pagination as well. If we just head over and have a look at this and bring back our pagination you can see that this will also break for pagination
09:38
as well so let's go ahead and go to page two we get the same article at the top here page four we get the same article so really the user is just stuck with the first amount of articles by a particular user which is not great. Okay so to get around this what we can do is create a dynamic cache key so now technically what we're doing is caching lots of different things based on the
09:59
request that we actually get through here so what we're going to do is say user dot and then x and there's no real rule for the cache keys that you create doesn't matter and we can say page dot y so really our goal is just to replace out the x and the y here just with the page and the user that have been selected now there are loads of different complicated ways you can go to do this if you find
10:22
yourself adding way too much here or getting a little bit complex then we need to really think of a different strategy but for now this is absolutely fine so what we're going to do is we're going to append on to here the user id from the request so let's say user id and we're going to do the same for the page as well so we're just going to append on request and page you can even
10:43
create a method for this to return this if it gets a little bit too long you could use something like sprint f to build this up really there are lots of different ways but i think this looks absolutely fine for now okay so now that we've done that we're including the user id and the page in the cache key so now when i hit the home page we get a list of these which will have none of them in
11:04
there so this is just the kind of default if we hit page two now we're going to go ahead and see a different set of articles but because we're now using a different cache key because the pagination key or the page has changed we're relooking these up in the database until we refresh the page so what that is then doing is caching page two as well if we go back to page
11:25
one and we give this a refresh we get the same thing back to page two this is now cached so it's working nicely if we go over now and add in a user id in here so i want to see articles from user three of course what we're now seeing is a list of articles from that user that will then be cached and then when we head over to user id one that won't be cached because we've not viewed
11:45
it yet but the next time around it will be now this kind of thing gets really complicated when you want to clear out specific individual cache keys because you have quite a few in here now let's say that we had how many pages have we got here 200 pages if we have 200 pages that means that we need to clear 200 different variations of this cache key plus all of the
12:07
users as well so this ends up creating a incredibly complex way to clear these out now you can solve this by using cache tags which don't actually work for the file driver so we'll cover that in the next episode when we look at clearing out this data for example when new posts are published and that's a really important part of this because it's great to
12:28
cache stuff but you also need to be able to clear this out effectively as well so there we go we have effectively reduced down the time of this page or the request duration of this we have a low memory usage and we have absolutely zero queries being performed on all of these pages because they are now cached
15 episodes1 hr 9 mins

Overview

Let's keep our Laravel applications feeling snappy! In this course, we cover the absolute fundamentals you need to keep in mind when building anything with Laravel.

While Laravel handles a lot for you, it's easy to fall into the trap of not considering and monitoring performance as you go. Keep these tips in your toolbelt, and you'll be able to develop faster apps, from the beginning.

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

Episode discussion

No comments, yet. Be the first!