Implementation Principles of Laravel middleware and details of laravel Middleware

Source: Internet
Author: User

Implementation Principles of Laravel middleware and details of laravel Middleware

This article describes the implementation principles of Laravel middleware. We will share this with you for your reference. The details are as follows:

#1 What is middleware?

For a Web application, before a request is actually processed, we may make various judgments on the request before it can be passed to a deeper level. If we use if else, the Code becomes more difficult to maintain and the coupling between systems will increase. middleware can solve this problem. We can separate these judgments into middleware to easily filter requests.

#2 middleware in Laravel

In Laravel, the implementation of middleware is actually dependent on The Implementation of The Illuminate \ Pipeline class. Let's first look at the code that triggers the middleware. It is very simple, that is, after processing the request is transferred to a closure, it can continue to be passed.

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

#3 Internal middleware implementation

As mentioned above, the middleware is implemented by Pipeline, and its call 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. Let's 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 does not do anything, that is, it sets the object for water treatment in the middleware, 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 very simple, that is, to set the middleware to be processed.

Then Method

The then method code is concise, but it is not easy to understand.

Public function then (Closure $ destination) {// The then method accepts a Closure as a parameter and is packaged by getInitialSlice. getInitialSlice returns a Closure, if you do not know what a closure is, first go to the PHP document $ firstSlice = $ this-> getInitialSlice ($ destination); // reverse the middleware array, mainly using the stack features, for more information, see $ pipes = array_reverse ($ this-> pipes). // do not check this call_user_func, it actually executes a closure returned by array_reduce: return call_user_func (// use array_reduce to process Arrays Using callback functions. We recommend that you first read the implementation principles of array_reduce in the PHP document. In fact, arrary_reduce has nothing to do. It is to wrap the closure and hand it over to call_user_func to execute array_reduce ($ pipes, $ this-> getSlice (), $ firstSlice ), $ this-> passable );}

Then there is no more, so all the middleware is finished, isn't it very elegant?

Because the second parameter of aray_reduce requires a function, let's take a look at 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 ));}};};}

It may be dizzy, and the closure returns the closure. Simply put, getSlice () returns A function A, and function A Returns function B. Why are two functions returned? Because $ next ($ request) is used to transmit objects in the intermediate transmission process, and $ next ($ request) indicates that the closure is executed, this closure is function A, and then returns function B, which can be passed to the next middleware.

The code is simplified as follows:

// $ Stack here is actually a closure. During the first traversal, the closure $ firstSlice will be passed in, and the function below will be passed in each time; $ pipe is the array_reduce ($ pipes, function ($ stack, $ pipe) {return function ($ passable) use ($ stack, $ pipe ){};}, $ firstSlice );

Let's take a look at this piece of code:

// Determine whether it is a closure. Here, it is used to determine whether the form of the middleware is a closure. If yes, it is executed directly and $ passable [Request instance] and $ stack [the closure passed to the next middleware] are passed in. and return if ($ pipe instanceof Closure) {return call_user_func ($ pipe, $ passable, $ stack ); // when it is not a closure, it is like this: Illuminate \ Foundation \ Http \ Middleware \ CheckForMaintenanceMode execution} else {// resolution, return the name, this $ parameters has been reading the source code for a long time and cannot be understood. It should be related to parameters, but it does not affect our analysis list ($ name, $ parameters) = $ this-> parsePipeString ($ pipe ); // parse the middleware instance from the container and execute the handle method return call_user_func_array ([$ this-> container-> make ($ name), $ this-> method], // $ passable is the request instance, and $ stack is the passed closure array_merge ([$ passable, $ stack], $ parameters ));}

Let's look at another image:

Each iteration is passed into the last closure and the middleware to be executed. Because the array is reversed and based on the advanced and later features of the stack, the first middleware 3 is packaged, middleware 1 is on the outermost layer. Remember, arrary_reduce does not execute middleware code, but encapsulates middleware.

As you can see, array_reduce will return func3 at the end, then call_user_func (func3, $ this-> passable) is actually
Copy codeThe Code is as follows: return call_user_func ($ middleware [0]-> handle, $ this-> passable, func2 );

The handle code in our middleware is:

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

Here is equivalent to return func2 ($ request), where $ request is processed by the previous middleware. As a result, the middleware process is complete, and it will be a bit difficult to understand, as long as you remember that the last step is to execute the middleware code by the outermost call_user_func.

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.