TheMrbikus TheMrbikus - 4 months ago 11
PHP Question

How does work middleware in Laravel 5?

I'm trying to understand how the middleware works in Laravel 5. I looked a Middleware Interface and understood that I must implement class, which has method "handle". In the "handle" method is invoked closure. But I don't understand, what passed in closure. What class will be invoke my Middleware? How it work under 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();


It right way, or not? I also can't understand, how i should called the next middleware in next() method in my MiddlewareCollection class.

Answer

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.

Comments