Explore how the middleware of Laravel is implemented

Source: Internet
Author: User
How is the middleware of Laravel implemented? This paper mainly introduces the implementation principle of Laravel middleware, and analyzes the concept, principle and related methods of laravel middleware in detail, and the use of the technique, which can be referred to by friends. We hope to help you.

Specific as follows:

#1 What is middleware?

For a Web application, before a request is actually processed, we may make a variety of judgments about the request before it can be passed on to a deeper level. And if we use if else this way, once the conditions need to be judged more and more, it makes the code more difficult to maintain, the coupling between the system will increase, and the middleware can solve the problem. We can make these judgments independent of the middleware, can be very convenient to filter requests.

Middleware in the #2 laravel

In Laravel, the implementation of middleware is actually dependent on the implementation of the class Illuminate\pipeline\pipeline, we first look at the code that triggers the middleware. It is very simple, that is, after processing the request to a closed packet can continue to pass.

Public function handle ($request, Closure $next) {  //do something for $request  return $next ($request);}

#3 Middleware Internal implementation

It says that middleware is implemented by pipeline, and its invocation is in Illuminate\routing\router

Return (new Pipeline ($this->container))            ->send ($request)            ->through ($middleware)            ->then ( function ($request) use ($route) {              return $this->prepareresponse (                $request,                $route->run ($request)              );            });

As you can see, the middleware execution process calls three methods. Take a look at the code for these three methods:

Send method

Public function Send ($passable) {  $this->passable = $passable;  return $this;}

In fact, the Send method did not do anything, is to set the need to stream water in the middleware object, here is the HTTP request instance.

Through method

Public function through ($pipes) {  $this->pipes = Is_array ($pipes)? $pipes: Func_get_args ();  return $this;}

The through method is also simple, which is to set up what middleware needs to be processed.

Then method

Really difficult to understand, then the method code is very concise, but it is not easy to understand.

The public function and then (Closure $destination) {  //then method accepts a closure as a parameter and then passes through the Getinitialslice wrapper, And Getinitialslice return is actually a closure, if you do not know what is the closure of the first to see the PHP document  $firstSlice = $this->getinitialslice ($destination);  Inverse middleware array, mainly using the characteristics of the stack, the use of the next  $pipes = Array_reverse ($this->pipes);  This call_user_func does not look at first, it is actually executed a array_reduce return of the closure of return  Call_user_func (      ///And then use the array_reduce to process the array with a callback function, It is recommended to first read the PHP document to understand the array_reduce principle. In fact, arrary_reduce do not do anything, is packaging closures and then handed over to Call_user_func to perform    array_reduce ($pipes, $this->getslice (), $firstSlice), $this->passable  );}

Then there is no then, so it is finished all middleware, is not very elegant?

Since the second parameter of Aray_reduce requires a function, we'll focus here on the source code of the Getslice () method

protected function Getslice () {    return function ($stack, $pipe) {  //here $stack      return function ($passable) use ($stack, $pipe) {        if ($pipe instanceof Closure) {          return Call_user_func ($pipe, $passable, $stack);        } else {          list ($name, $parameters) = $this->parsepipestring ($pipe);          Return Call_user_func_array ([$this->container->make ($name), $this->method],          array_merge ([$passable, $stack], $parameters));}};};    }

See may be very dizzy, closures return closures. The simplification is Getslice () returns a function A, and function a returns function B. Why do you want to return two functions? Because we pass the object with $next ($request) in the middle of the pass, and $next ($request) means that the closure is executed, the closure is function A, and then returns function B, which can be passed on to the next middleware.

To simplify the code is:

Here $stack is actually closed packet, the first time will pass through the $firstslice this closure, each time will be passed in the following function; And $pipe is every middleware array_reduce ($pipes, function ($stack, $pipe) {    return function ($passable) use ($stack, $pipe) {  };}, $firstSlice);

Let's look at this section of code:

To determine whether it is a closure, here is the way to determine if the middleware form is closed, if it is executed directly and passes in the $passable[request instance] and $stack[to the next middleware, and returns the IF ($pipe instanceof Closure) {    return Call_user_func ($pipe, $passable, $stack);//It's like this when it's not a closure illuminate\foundation\http\middleware\ Checkformaintenancemode Execute} else {    //parse, return the name, this $parameters read a long time source or do not understand, it should be related to parameters, but does not affect our analysis  list ($name, $ Parameters) = $this->parsepipestring ($pipe);   Resolves the middleware instance from the container and executes the handle method  return Call_user_func_array ([$this->container->make ($name), $this- Method],   //$passable is the request instance, and $stack is the transitive closure  array_merge ([$passable, $stack], $parameters));  }

Look at one more picture:

Each iteration passed in the last closure and need to execute the middleware, because the inverse of the array, based on the advanced post-stack features, so middleware 3 is first packaged, middleware 1 is the outermost layer. Remember, arrary_reduce he does not execute middleware code, but packaging middleware.

See here should understand, Array_reduce will eventually return to Func3, then Call_user_func (func3, $this->passable) is actually

return Call_user_func ($middleware [0]->handle, $this->passable, FUNC2);

And the handle code in our middleware is:

Public function handle ($request, Closure $next) {  return $next ($request);}

This is equivalent to return Func2 ($request), where the $request is processed through the previous middleware. So the process of the finished middleware is over, it will be a bit of understanding, as long as the last is the outermost call_user_func to execute the middleware code

Related recommendations:

Laravel Optimized Split routing file

Laravel using pagination plug-ins for custom paging

Laravel writing the App interface (API)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.