I'm trying to understand how the middleware works in Laravel 5. I looked at Middleware Interface and understood that I must implement a class, which has a method called "handle". In the "handle" method, closure is invoked. But I don't understand, what should be passed in closure. What class will invoke my Middleware? How does it work under the hood? May be it is like "foreach" and all Middlewares will be invoked by turn? UPDATE: I'm trying to implement my own middleware:
interface Middleware
{
public function handle($request, Closure $next);
}
class MiddlewareCollection
{
private $middlewares;
private $request;
public function __construct(Array $middlewares, $request)
{
$this->middlewares = $middlewares;
$this->request = $request;
}
public function run()
{
$this->next(current($this->middlewares), $this->request);
}
private function next(Middleware $middleware, $request)
{
$middleware->handle($request, function($request) {
//How can I call the next middleware?
});
}
}
class FirstMiddleware implements Middleware
{
public function handle($request, Closure $next) {
echo $request.'first ';
return $next($request);
}
}
class SecondMiddleware implements Middleware
{
public function handle($request, Closure $next) {
echo $request.'second ';
return $next($request);
}
}
class ThirdMiddleware implements Middleware
{
public function handle($request, Closure $next) {
echo $request.'third ';
return $next($request);
}
}
$middlewares = [
'first' => new FirstMiddleware(),
'second' => new SecondMiddleware(),
'third' => new ThirdMiddleware()
];
$middlewareCollection = new MiddlewareCollection($middlewares, 'Request');
$middlewareCollection->run();
Is it the right way, or not? I also can't understand how should I call the next middleware in next() method in my MiddlewareCollection class.
Laravel framework comes with several middlewares, including midlewares for — authentication and CSRF protection. The default middleware are located in the app/Http/Middleware directory.
We can also use the controller constructor to assign the middleware. It is more convenient as it restricts the middleware to only specific methods on a controller class.
This blog post is really useful for explaining how middleware works, and how you can build some from scratch.
However I will use an example that ships with Laravel, the auth middleware (app/Http/Middleware/Authenticate.php
). This middleware protects routes and ensures the user who is trying to access them is logged in.
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
}
}
return $next($request);
}
The handle
function is what does all the work for us, in this case it starts off by accepting the $request
which is where we want to be going or the request that we are sending to the server.
Next we are checking if the user is logged in or is a guest with if ($this->auth->guest())
If we are logged in then this would return false and we would move on to return $next($request);
which would allow us to carry on as normal.
If we aren't logged in and are a guest, we pass this statement as true and move on with the if
statement.
We would then hit:
if ($request->ajax()) {
return response('Unauthorized.', 401);
}
This may be self-explanatory but it check to see if the request is an ajax call and if it is then it will return a 401 unauthorised response.
If it isn't an ajax request then we hit this:
else {
return redirect()->guest('auth/login');
}
Which will redirect the guest to the login page. Once they are logged in the request can continue and their request will be carried on as normal.
As such, I could protect the route www.mywebsite.com/admin
with this middleware and if I wasn't logged in then I would be redirected to www.mywebsite.com/auth/login
and once I had logged in I would return to my original request www.mywebsite.com/admin
without any trouble.
As I mentioned first though, check out that blog post because it does have some useful explanations and simpler examples.
Middleware, on Laravel prior to 5 were known as filter. Middleware intercepts the request and then handle inside your middleware class is responsible for the next job on what to do. There are two types of middleware based on how you handle that.
The before middleware is checked before the control is passed to the controller. The logic is inside your handle method. Like, you want a logged in your to post on your guestbook. So, if you use before middleware is applied, and your logic is like
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
The after middleware checks after the controller has completed all its job and the response is going to be passed to the user. For this, you can think it as an API request has been made and you want to refresh the token on every request complete. for this the code will be like,
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
Here, for simplicity, you can think the $next method as it's going to pass the control to the controller. For before middleware, it's checking the logic then it's going to return the control to the controller and finally returning the response.
On the other hand, the after middleware is passing the control to controller, when the controller is done completing its job, then something is stored on the $response variable and performing some logic. After that it's returning the $response.
Hope it's clear now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With