Playing
01. Caching Authenticated Users in Laravel

Episodes

0%
Your progress
  • Total: 12m
  • Played: 0m
  • Remaining: 12m
Join or sign in to track your progress

Transcript

00:00
By default, every request to your Laravel application will refetch the user out of the
00:05
database with a database query. We can see this with Laravel debug bar and we're selecting all of the columns by default in the users table, of course where the ID matches the ID of the user that I'm logged in as. Now for high traffic applications or if you are dealing with speed issues with the data that's coming from your users table, you can actually go ahead and cache this.
00:29
So we're going to be looking at how to do that and how to create a new driver for our cached authenticated users within Laravel, but we're of course also going to cover busting or clearing the cache when something changes. It's really important we do that as well. Let's just take a really quick look at what this involves. So if we come over to our config and auth
00:52
file, at the moment by default we have this eloquent driver which is always going to pull this data from the database. What we're going to be doing in this video is creating out a cached eloquent driver which means when we come over and give this a refresh, sure enough we do get an initial database query to actually fetch this data. This data will then be cached and you can
01:14
see that any subsequent requests I make here don't make that database request. So before we start, I wouldn't recommend this just doing this for every single project. Really the benefit of this is if you have a very high traffic application or fetching users is getting in the way and you have some sort of speed bottleneck there. Okay, let's go ahead and clear everything out. We'll
01:35
start from scratch and see how we can cache authenticated users in Laravel. Okay, so I've gone ahead and created a completely fresh project here and I've registered a user and I've logged in. First step, let's go ahead and do a composer require Laravel debug bar so we can monitor the queries within our application. Okay, now that's done that should just automatically appear for us
01:58
and as you can see we've got quite a few queries here by default. Just to make this a little bit clearer I'm going to head over to EMV and I'm going to swap over the session driver from database to file just so we can focus on the one query here that we're trying to get rid of which of course is fetching that user every single time. So the question is where does this come from? How does
02:21
Laravel choose or where does Laravel fetch this user? Well since we've pulled up Laravel debug bar already you can see that this comes from the Eloquent user provider. So let's go ahead and open that up and just see what this contains. So let's say Eloquent user provider and this of course is part of the base framework so we don't want to modify anything here. Let's go ahead and take a
02:44
look at what this does. So we can see here it implements a user provider so that's sort of a common provider between all of the different methods that we could potentially use to fetch a user and let's go down and have a look here. So we've got the model here to fetch we've got retrieve by ID so that kind of looks like what we would want to override and you can see here that
03:06
we get a method called this new model query here which goes ahead and either creates that model for like a user a completely empty user or it goes ahead and takes the model and grabs that back for us. So basically just fetches that out of the database using the ID of the user and we've got some stuff in here to like set hashing and get the model and all that kind of stuff. Now the good
03:32
news is we don't really need to when we want to cache this kind of data we don't really need to override for example the get or retrieve by ID method we don't need to override this we just need to call it from our own provider and then cache the result of this. So let's go ahead and try this out and see how we would do this. So if we go over to our app service provider you could
03:57
create out a separate service provider for this if you wanted to. The key part of this is going ahead and either using the auth helper or you can use the auth facade for this I prefer always using the helper and we're going to go ahead and say provider. Now what this method allows us to do is register a new provider and we just want to return that provider. So at the moment within
04:20
the base of the framework it will look like this eloquent which is defined over in config and auth so if we just look for the driver that's being used here you can see that the driver for our users is eloquent this is how it would have been registered and we would have had a closure in here that returns that new eloquent user provider that's the thing that we just opened. Now obviously
04:46
this isn't what we want to do we want to get rid of this we want to create our own provider by extending that base eloquent provider that we've just opened. So let's give this a new name I'm just going to call this cached eloquent because technically we're still using eloquent but we're just putting a caching layer in front of this. Now when we go ahead and invoke this the callback
05:06
that we get here has an instance of our application under illuminate foundation and application we're going to need that as well to pull our hasher out to pass into our eloquent user provider and we also have an array of config items as well which we can use to pass in the model which exists just here so that gets passed into here as well. Okay so we want to take the eloquent user provider we
05:32
basically want to extend it override retrieve by id but grab back a cached version of this so how do we do that well where do we put this well we can just put this within our app directory here I'm going to create our directory in here called auth and we can even create a directory in here called providers as well if we wanted to keep things nice and tidy and we are just going to
05:54
create our php class in here and let's call this cached eloquent user provider so basically eloquent user provider with cache tacked onto the end of it with this we're going to extend the eloquent user provider that we've already opened and in here we're going to go ahead and override the retrieve by id method and we're going to return something different for now let's go ahead and
06:21
just fill this in with the identifier and let's go ahead and just return exactly the same thing so let's just say parent retrieve by id passing in the identifier so once we do switch over our provider to this one nothing will change at all and then we can just wrap this and cache it okay so let's take our cached eloquent user provider let's go over to our app service provider and
06:47
let's return a new instance of this directly in here of course make sure we go ahead and import this and the two things that we need to pull in if we just take a look at the base here is the hasher for our application and the model which comes from our config so to do this we just want to pass in from our application the hash out of the container and then from that config we want
07:12
to pass in the model which is the user model okay so now that we've done this let's switch over over in our auth config this from eloquent to cache eloquent now that we've registered that over here and let's see what happens and there we go we don't see any difference whatsoever because remember what we're doing here is just overriding the retrieve by id method and calling exactly the
07:36
same one what we can do now though is we can go ahead and wrap this in a cache how do we do that well of course we use laravel's caching functionality and you can do this however you'd like you can give it whatever key that you like you can cache it for as long as you like it doesn't really matter so let's go ahead and say cache remember let's put this under the key user underscore and then
08:00
let's give the identifier the identifier by the way in my case is going to be one so it kind of makes sense that we cache this under that key and that makes it nice and easy next is how long we want to cache this for so let's grab the current time stamp with carbon and let's just add a day onto there it doesn't really matter too much and let's go ahead and create our closure here which
08:21
returns what we want to cache and in our case of course that is going to be the result of retrieve by id and of course we also need to use the identifier here to bring that into scope okay so now that we've done this let's head back over to our application and let's see the difference now at the moment i think our caching is set at the database level which of course is just going to
08:42
completely negate everything that we've just been doing so just before we refresh this let's go ahead and check out what our cache store is and yeah sure enough it's the database so that would just replace fetching the user from the database with fetching the user from the cache from the database and it doesn't really make sense so we would want to change that to something like redis
09:01
or whatever else we're using okay so now when we refresh of course that query to fetch the user is now gone now this is all well and good so we've switched this over and of course you can modify this to do whatever you want you could do something different in here fetch some other details and return them whatever you needed to do that's the basics of this but we do have a problem and that
09:23
is busting the cache so for example if i go ahead and change over my name over here and hit save this will have actually changed in the database you can see here that has been updated but because we're caching this data this is now cached for a day and it's highly unlikely i'm going to see this new value come through anytime soon so this is the tricky part caching the user
09:47
that we get returned is super simple we've done that in pretty much no time but now we need to figure out when to bust the cache or clear the cache so let's go and do this now and then you'll just need to think while you're building your application anything that interacts with the user or updates the user you will need to bust the cache okay so a pretty much catch-all approach to
10:10
busting the cache for the user whenever anything changes is to go ahead and make out an observer so let's create our user observer here and let's hop over to our user model and let's attach this so we can just use the php observed by attribute or the laravel observed by attribute here and we can pass in the user observer into there what we can now do is create out methods that hook into
10:36
eloquent like updated so when a user gets updated and that's hooked into that model what do we want to do well we want to just completely forget our user underscore and the user's id cache value so let's go ahead and say cache and forget and let's pass in user underscore this will be the user that gets updated so all we need to do here is just pass in the user id and remember that matches up
11:00
to the identifier that we were working with earlier we can do the same thing as well when a user is for example deleted these are the two that i would add if i was building this caching functionality into my own project but then of course we have to think about other scenarios where the user would get updated but you need to think about other instances where you are updating the user for
11:20
example if you were somewhere in your application using db table users to update a user or a bunch of users this would not trigger the cache forgets you'd have to manually do that so really easy to add this caching functionality but just make sure that you are clearing the cache in the places that you need to okay so now that we've added this user observer let's go over and have a look here
11:47
sure enough the data is still cached but let's just try and update this value to alexander again and sure enough you can see that has now been updated because we are clearing the cache and therefore refetching this data from the database when we give this a refresh though we're back to zero queries and we're back to a cached user of course if i were to go ahead and delete this user
12:09
that cache key and value would also be removed so super easy to add this caching just be really careful make sure you clear the cache where you need to and i probably wouldn't pull this in for every single project but it can be really helpful and luckily with laravel having the ability to add in these new providers it actually makes it pretty straightforward to do
1 episode 12 mins

Overview

For even faster gains on high-traffic Laravel applications, you can cache authenticated users to avoid a trip to the database.

In this snippet, I'll show you how — but this isn't a quick fix; we'll have to consider what happens when the user gets updated or deleted.

Let's cache!

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

Episode discussion

No comments, yet. Be the first!