Middleware Request Filtering0:00
Middleware gives us a really easy way to filter incoming requests. So if I browse to app/Http/Middleware, you'll see that Laravel 5.1 comes with just a few out of the box. One for authenticate. So if we take a look, let's see what's happening here. If the User is a guest, meaning they're not signed in, well, in that case, you need to be authenticated to access this endpoint or this route. So we will either return an unauthorized response, or if it's not an AJAX request, we will redirect you to the login page. Otherwise, if you are signed in, well, take a look at this syntax here, return next request. Think of this sort of like a stack or like a pipeline. You can create any number of middleware, and Laravel for each request, at least where it's relevant, is going to cycle through all of these middleware and trigger the handle method. That way, for each layer in the stack, you have
Global vs Route Middleware0:50
and Laravel for each request, at least where it's relevant, is going to cycle through all of these middleware and trigger the handle method. That way, for each layer in the stack, you have the opportunity to either, if everything succeeds, pass it on to the next item in the stack, or if something doesn't meet your criteria, you can intercept the request and do anything you need to, like redirect the user to a different URL on your site. Okay, so we have a middleware, but how would we activate this, so to speak? Well, the first thing I want to show you is this. If we switch over to our HTTP Kernel, you'll see two different sections here. We have middleware on top and route middleware on the bottom. So what exactly is the difference between these two? It's very easy. Think of the top, the middleware property, this is for middleware that will be executed for every single request.
Applying Auth Middleware2:29
Well, we can attach middleware in two ways. One, we can do it within a callback closure here, or we could do it from our controller within the constructor portion. Let's do it here for now. I'm going to attach some middleware, and the key was off. Just to make sure we're on the same page, I'm referencing this key, which points to the authenticate middleware. So now by adding that, I've specified that as part of the request, I want to trigger this handle method, where we make sure that the user is not a guest. Okay, well, this looks good. Why don't we boot up a server and see if it works? php artisan serve, and if we now hit that in the browser, there we go. It redirected us to the login page, and in this case, we just don't have an endpoint set up for that. But it is working like we expect. If we try again, there you go. It immediately redirects us there, because we applied the middleware that filtered the incoming request. So if I go back to Sublime, what about
like we expect. If we try again, there you go. It immediately redirects us there, because we applied the middleware that filtered the incoming request. So if I go back to Sublime, what about this other one? Well, think of this as the opposite. This is like our guest filter, and if we switch over to Kernel real quick and scroll down, there we go. It has a key of guest. So if we take a look at that one, and remember, you can create these middleware yourself, and for any typical application, you likely will. So in this case, if the User is signed in, well, in that case, we'll send them to their dashboard, or this is part of your app directory, so you can modify this however you want. It's not the sort of thing where a composer update will overwrite these files. This is all for you. You can edit it however you need to. Anyways, if the User is a guest, then everything's good. So we'll pass the request on to the next item in the stack. Okay, so why don't we create one
Creating Subscriber Middleware4:12
You can edit it however you need to. Anyways, if the user is a guest, then everything's good. So we'll pass the request on to the next item in the stack. Okay, so why don't we create one ourselves? What might be a common middleware? And here's one I use at Lerikast, in fact. I often need a way to state that in order to view this page, not only do you have to be authenticated, but you also need to be a subscriber at Lerikast. And a good example of that is, well, you can sign up for a free account and just participate in the forum. So in a situation like that, the user would pass the auth middleware. They are signed in, but still, they shouldn't be allowed to view videos that are only for subscribers. So that's a different check, and that should have its own middleware. Let's create one together. Close this out. php artisan make:middleware. We have a generator for that, and you can name this anything you want. Just follow a convention and stick to it.
. Let's create one together. Close this out. php artisan make:middleware. We have a generator for that, and you can name this anything you want. Just follow a convention and stick to it. I very much like what Laravel does. You describe exactly what it does. So if we want one for subscribers, you could do something like redirectIfNotSubscribed, or you could even do something like mustBeSubscribed. That's what I do at Laracasts. So let's generate that, and you'll see we have a new one right here. Now before we handle the logic, let's register this within our Kernel right here. Now what key do we want to give it? We could say subscribe, or subscribed, or subscriber. It doesn't matter. Whatever you want. Why don't we go with subscribed. And that will point to app/Http/Middleware/mustBeSubscribed. Okay, that's all set up, which means from our routes.php file, we can add that middleware by referencing the key. So now how do we handle
app.http, middleware, and must be subscribed. Okay, that's all set up, which means from our routes.php file, we can add that middleware by referencing the key. So now how do we handle the logic for this? What do we really want to check? Well, let's use pseudocode to start. If the User is logged in and the User is currently subscribed, then and only then does our check quote-unquote pass, at which point we can pass it on to the next layer in the stack. Otherwise, if these two conditions do not pass, well, it failed, so we're going to respond to that by typically redirecting the User somewhere else in the application. You don't have permission to access this route. Okay, so that means if our check succeeds, we can pass it on to the next layer in the stack. Otherwise, or we can just add it down here, we can redirect them somewhere. And why don't we, in this case, just redirect them home,
succeeds, we can pass it on to the next layer in the stack. Otherwise, or we can just add it down here, we can redirect them somewhere. And why don't we, in this case, just redirect them home, but maybe you want to redirect them to a sign-up page. So if you try to access this video-only page, well, you don't have permission, so we're going to redirect you to a subscription page or an upgrade page where you can fill out a form to subscribe, and then you can come back and access it. But in our case, we don't have any kind of application here, so we'll redirect to the home page. Cool. So now just for our condition, how do we set that up? Well, you'll see that we accept the request here, and one of the methods that we can access off of the request object is user, and essentially that's going to translate to something like this, auth()->user(). So we're going to say if we have a user and the user is subscribed, well, how do we represent that?
and essentially that's going to translate to something like this, auth user. So we're going to say if we have a user and the user is subscribed, well, how do we represent that? Well, yeah, we could add some logic here, or let's make the user responsible for that. So maybe we could just say user subscribed. If you use something like laravel cashier, I think you get a method just like that on your user object. Or if you're building this yourself and you want something like that, that would be fine too. So why don't we do this? Why don't we save that to request user, and then we'll clean that up just a tad. Okay, so that looks good. But now, of course, if we run this, well, we don't have an isSubscribed method. So why don't we do that? Now, I've already run the basic migrations that come with Laravel. So we do have a users table, but beyond that, we don't really have anything. So why don't we add this
we do that? Now, I've already run the basic migrations that come with Laravel. So we do have a users table, but beyond that, we don't really have anything. So why don't we add this at the bottom? Method is subscribed. And here, well, you would do whatever you need to to check if the User is subscribed. So for example, maybe you return a boolean, and you check some column in the table, like subscribed. Maybe that's just a one or a zero for your system. Or maybe you're checking something like if you work with Stripe, maybe you're checking to see if there's a Stripe ID. If there is, then they're currently subscribed. If there's not, if it's null, then you're not subscribed. It really doesn't matter. It just depends upon how your app was built. We're going to fake that and just say true for now. Let's assume the User is subscribed. Okay, so let's see how this is going to work. The User makes a request, and it's going to go
built. We're going to fake that and just say true for now. Let's assume the User is subscribed. Okay, so let's see how this is going to work. The User makes a request, and it's going to go through all of the middleware that we have. In this case, we've opted in to the subscribed middleware that we defined right here. So that means we're going to call a handle method on mustBeSubscribed. Next, within here, we check to see if we have an authenticated User, somebody signed in, and also if that User is currently subscribed to our website. If that's the case, they're good to go. We can allow them, so we will pass it on to the next layer in the stack. But if this condition fails, well, you don't have permission to view this page, so we will redirect you to the home page. Let's try this out in the browser and see how it works. But you know what, real quick, it just occurred to me, we redirect the User to the home page, but we were using that as our test
Testing Subscription Middleware10:15
Let's try this out in the browser and see how it works. But you know what, real quick, it just occurred to me, we redirect the User to the home page, but we were using that as our test route. So why don't we duplicate this, and we'll store that as test. And then here, we just won't have any middleware. That's fine. Return subscription only page. Okay, that should do the trick. So if I switch to Chrome, here's our home page. And if we visit test, that should redirect us back, and it does. Because remember, the condition in our middleware failed. We're not even signed in, so that first part of the condition did not pass. Why don't we create a quick test User to see if this works? Route::get(login). This will just be temporary code. But within here, let's just say App\User::forceCreate(, since I haven't set any fillable fields or anything like that. And all we have to do is provide a name, John Doe. Email is john@example.com. And then
let's just say User::forceCreate(['name' => 'John Doe', 'email' => 'john@example.com', 'password' => bcrypt('password')]); All right, so we have our User. Let's log them in. And then redirect to the home page. Okay, cool. So when we hit that route, we will create a User, which we would remove immediately after doing that. But we get our User, we log them in, and we redirect to the home page. That way, when we hit the test route, well, hopefully it should work. Back to Chrome, login, creates that User, which means if we hit our test route, there you go. Everything passed. So let's go back. The User is signed in. And also, our isSubscribed method returned true because we hardcoded that. Let's now return false. And if we try it again, well, that second part of the condition should fail. So once again, it redirects us. So hopefully you see
When to Use FormRequest12:11
returned true because we hardcoded that. Let's now return false. And if we try it again, well, that second part of the condition should fail. So once again, it redirects us. So hopefully you see what I mean when I use that term filtering. Middleware gives us a really easy way to filter incoming requests and protect our routes however we need to. But now you might come to this situation where you want to check permissions. So for example, imagine that when you visit a URI to edit a Post, like something like that. Well, maybe you want to say only allow a User to access this page if they're signed in and they created the Post that they're trying to edit. That way, we don't allow guests to access that page. Well, you might be inclined to put that sort of logic in a middleware, and you might be able to get away with that. But really, that's not quite what it was intended for. In a situation like this, your check would probably be
of logic in a middleware, and you might be able to get away with that. But really, that's not quite what it was intended for. In a situation like this, your check would probably be to find the Post where the id equals 1 and also where the user_id equals the id of the person who is signed in. And if you get any results, well, the person making this request has permission. Otherwise, they don't. So because that check is very, very specific and often will be exclusive to a particular route or an endpoint, in those situations, it makes more sense to use a FormRequest. And don't worry, we'll get to those very soon.
