Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does middleware work in Laravel 5?

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.

like image 472
TheMrbikus Avatar asked Nov 11 '15 21:11

TheMrbikus


People also ask

What is default middleware in Laravel?

Laravel framework comes with several middlewares, including midlewares for — authentication and CSRF protection. The default middleware are located in the app/Http/Middleware directory.

Can we use middleware in controller?

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.


2 Answers

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.

like image 163
James Avatar answered Oct 17 '22 08:10

James


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

  • check if the user is not logged in
  • redirect them back to login page
  • otherwise, let the request proceed as it was
and the code will be like this,
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.

like image 23
ssi-anik Avatar answered Oct 17 '22 08:10

ssi-anik