7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

1.2 How It Works: Laravel Middleware

In this lesson, I’ll show you how middleware works, how it flows through an application, and how to create middleware of your own.

Code Snippet

Here is an example of some simple middleware that replaces all instances of “Hello” with “Goodbye” in the current response.

public function handle($request, Closure $next, $old = 'Hello', $new = 'Goodbye')
{
  $res = $next($request);
  $res->setContent(preg_replace("/$old/", $new, $res->getContent()));
  return $res;
}

Related Links

1.How It Works: Laravel Middleware
2 lessons, 13:05

1.1
Introduction
00:18

1.2
How It Works: Laravel Middleware
12:47


1.2 How It Works: Laravel Middleware

[SOUND] Have you ever wanted some bit of functionality to run before or after every request? One example may be that you want to verify that you have an authenticated user before allowing access to a controller. Another may be that you'd like to log a rough benchmark of how long a request takes from end to end through a Laravel application. If these sound familiar, then you may be looking for Laravel's Middleware. So what is middleware? Simply put, it's supporting code that surrounds your application. It can inspect, transform, or stop a request before it even reaches the router or controller. And likewise, it can inspect transform or replace a response before it makes it back to the browser. You can even do both from the same function. Well, how does that work? Well, that's what we're here to learn today. I find that teaching this concept visually helps to demonstrate the flow through the code. So let's start off with a quick animation of how a request travels through the system. One of the clearest representations I've found is to draw the application as a circle and consider it much like an onion. At this thin outer layer, we have Laravel's bootstrap and tear down logic. And then we'll encounter the Middleware for our application, and this could be any arbitrary number of Middleware, but we're going to use two for our example. And then the core has our real application code. This is all the code between when a router controller action starts doing work until the point it returns from that function. Now let's visualize how a request comes into an application. First to passes through the bootstrap logic, then it will pass through all of the Middleware, into our application logic, then right back. Through that same Middleware in the opposite order, and finally passing through levels logic to send the request back down to the browser and finish up the code execution. Looking at this picture you might be feeling like you've seen something like this before but maybe you can't quite put your finger on why it looks so familiar. Let's try looking at it in text form to see if that helps. We'll start off everything inside some parentheses. First we'll call Laravel, then our first Middleware, second Middleware and then are application. And we can finish off these parentheses, if you ever use the list language, it may be obvious where I'm going with this. But since it's a PHP screencast, let me tweak this a bit into a more PHP compliant file. We'll start off with our PHP tag, we can delete this surrounding parenthesis, we'll add a dollar sign to all of our words. And then of course we'll end up for a semi-colon. So, as you can see here with some closures, we're doing a little bit of functional composition, and by doing just a little bit of this we have the ability to write a Middleware stack. Laravel takes your list of Middleware and executes them with a bunch of higher order functions as we'll see soon. At this point you may be thinking to yourself that this code will actually evaluate from right to left. Meaning that the application would execute in the middle where to and so on. Since most languages have the arguments evaluated before they're passed into a function, well you're correct that this is indeed the case. So we're gonna have to do some higher order function magic to make this work. If you'll indulge me for a minute, I'll give you a quick idea of how all of these works. It isn't necessarily the focus in the Screencast but I think it's an important piece to know. If you'd like to see the exact implementation, check out Laravel's pipeline class. Let's define this Laravel function as a closure that takes another closure F as it's only argument. And inside of the function we're going to have a request object, which for the sake of simplicity is really gonna be the integer 1. Now, the only responsibility this function has is to invoke the function that's being passed to it, and pass the request along. Now we're just gonna add some additional logging here. And we'll say Response from Middleware And we concatenate the request. And we concatenate a new line just to keep it pretty. And for the sake of being able to observe the flow of information through these functions, we're gonna add some additional logging. We'll say Starting Laravel, and then we'll just duplicate this below and name it Ending Laravel. Next we're gonna define our M1 and M2 Middlewares as a function that also takes a Closure which will call $next. And well I could define these as two separate functions, it's easier to do it this way but in the real world you would have two completely different Middleware. Now the big difference in this function compared to our Laravel function above is that we're going to return another function. This function takes the request as a parameter, and we're going to use the next argument from the scope above. Now what does this do by returning another function? Will device the execution of the code inside of the return function, Untill it gets invoked inside the body of our Laravel function or inside of another Middleware. In other words, this function we're returning is the function f that we're invoking above inside of the Laravel function. So, to get at some logging, we gonna say that we're starting our Middleware and I'm gonna cheat and use the request number as the number for our Middleware. So, I'm gonna put that. Next we gonna buy an available res to the result of calling our next function passing in request plus 1, that way we increment our Middleware number. And this demonstrates that we can modify the request before we send it to the next Middleware. Then I'm just gonna duplicate the line above and say we're returning the middleware to show that we're done with this one. And then we're gonna return the result, put in a blank space and we will concatenate meet the requests to show that we can modify the response as well. Finally, we'll define our function app below and this was nice and simple, it only takes a request and we're gonna echo out some information. We'll say Running app with the request and we're going to pass in the request itself, and a new line. And then we're just going to return the string response. And this would represent returning a response object from Middleware controller. Now what we could have made this exactly like the Middleware functions where it would return this function inside of another. This lets us represented as the end of the nesting Middleware. Jumping to the end of our file, let's go ahead and execute our script and I'll put the result in line in the editor. Walking through this, we boot Laravel, execute Middleware one, then two, then our application. They are returned to Middleware two, turn to Middleware one, get the response from our Middleware, which is response 2, 1, due to concatenating the strings together. And this is where Laravel would wrap up, and return the result to the browser, and this is exactly like that list looking code we showed before, and like the animation I showed at the beginning. If some of the details and nuances of this code are a bit confusing, or if you have a hard time grocking the pipeline class, don't stress it. As long as you understand this flow you'll be able to build powerful Middleware perfectly well. Now, the theories out of the way. Let's move into some concrete examples. I'm gonna build up a fresh version of variable, with the built in server command. Next we're gonna jump in to our routes and instead of view here we're going to return the string Hello. So now we have this page, do we get Hello's expected? I'm just going to stick to using Perl for the end points today since the examples are going to be pretty simple. Now let's start off basic with a built in Laravel middleware Is part of the foundation package and its name check for maintenance mode. The constructor simply takes an instance of the application container, which level will handle for you. Next, we have handle which is the method Laravel will call to invoke your Middleware. The Middleware stacked wraps is in another function automatically, and it instructed layer in the pipeline. So we simply need to have handle except the current should appear request and the next middle word will be invoked. Even if you're in familiar with this particular level feature the code is easy enough to follow. If the app is down for maintenance that we want to throw a maintenance mode exception with some parameters. Otherwise we'll simply return the result of calling the next middle work to keep the pipeline going. I like this Middleware because it demonstrates how we can both keep the light pipeline flowing and halt further processing on a request. Why we want to hold a request, you might ask. Several reasons. Preventing resource consumption, preventing access to authenticated routes, rate limiting or like this, preventing access of the site when it's in maintenance mode. Now we know our say returns Hello when not in maintenance mode. So let's turn maintenance mode on by writing php artisan down. And that will check our site again and I'll just grep for be right back because I know that string is in there. And there it is, our application is down. So now it will simply run php artisan up to bring our application back online. And our site's back up and running, now let's try creating our own. But since we already know the requests can be modified, let's instead modify the response. I'm going to run a PHP artisan make Middleware and we'll call it word swap Then we'll open it up, and to get this set up how we need it, we're going to assign the result of the next closure to res. And then we're going to return it. Next, I'm going to edit the HTTP kernel, and I'm going to add our Middleware to every request by appending it to the array here. If we curl the request again We should still see Hello and we do. So let's modify our middleware a little bit. And in here, we're gonna modify the response. We're gonna set the content to the result of replacing all of the instances of the word Hello with Goodbye. And now if we curl it we get Goodbye. But maybe we'd like to make this word something we can set outside of the function. Doing this is really easy and Laravel. Let's add two more optional arguments, old which will set to the default value of Hello, and new which will set the default value of Goodbye. And now we'll swap out this code down here in the Replace as well. We're running the code shows that everything still works. So set this from outside of the Middleware itself. Let's up back into the kernel and remove our Middleware from every request and instead we'll register it as route Middleware under the key swap. So now we can add this Middleware to our routes in a few different ways. The facets is the pop up right here in the Web Middleware group in the middle of this file. So after Middleware name swap, we're gonna separate the argument list with a colon and we're gonna replace Hello with Hola. When we rerun curl, we get Hola back. And now to demonstrate an alternate way to add this Middleware, or move this from the web group, jump over to our routes and then on our home route will chain another method named middleware and we'll pass and swap: Hello, Ciao. If we curl again we see Ciao. Now there is one last thing I want to demonstrate and that is the terminable method inside of a Middleware. Since work can be done after the response is sent to the browser the terminable method allows you to hook your middleware into this part of the lifecycle. The docs say the use case of persisting session information after the response returned. We are instead as you may expect going to do more random things with strings over in our middle where we're going to get go ahead and create the function terminate. And this takes two arguments the current requests like handled, and the already sent response. Our terminate method is going to sleep for two seconds and then it's going to echo out means Goodbye to help translate child to the user to go back over to curl and run a request. So you might be concerned that the response wasn't actually sent to the browser before the Middleware ran. What's really going on here is that curl buffered the response and your browser isn't going to do that by default. So, if I pass the end switch to my current quest. We can see ciao and then means goodbye appears two seconds later. And that is Laravel Middleware in a nutshell. We've explored how it works at a lower level, the features that we can use at a high level, and how they function overall. The next time you go to create some custom Middleware, just remember what we learned here, start small and then build up to what you need.

Back to the top