This paper illustrates the principle of laravel middleware implementation. Share to everyone for your reference, specific as follows:
#1 What is middleware?
For a Web application, before a request is actually processed, we may be able to 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 will make the code more difficult to maintain, the coupling between the system will increase, and the middleware can solve this problem. We can make these judgments independent of the middleware, can be very convenient to filter the request.
Middleware in the #2 laravel
In Laravel, the implementation of the middleware is actually dependent on the implementation of the Illuminate\pipeline\pipeline class, let's take a look at the code that triggers the middleware. Very simply, the process of handing the request to a closure can continue to pass.
The public function handle ($request, Closure $next) {
//do something to $request return
$next ($request);
Internal implementation of #3 middleware
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, that is, set up the need for streaming 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;
}
Through method is also very simple, is to set the need to go through which middleware processing.
Then method
Really difficult to understand, the then method code is concise, but it is not easy to understand.
The public function then (Closure $destination) {
//then method takes a closure as an argument and then passes Getinitialslice Wrapper, And Getinitialslice return is actually a closure, if you do not know what is closure first to see the PHP document
$firstSlice = $this->getinitialslice ($destination);
Reverse middleware array, mainly using the characteristics of the stack, use the next
$pipes = Array_reverse ($this->pipes);
Don't look at this call_user_func, it actually executes a array_reduce return
call_user_func (
///next to use the callback function to process the array with the Array_reduce). It is recommended to go to the PHP document to read the implementation principle of array_reduce. In fact, Arrary_reduce has nothing to do, that is, packing closures and handing them over to Call_user_func to perform
array_reduce ($pipes, $this->getslice (), $firstSlice), $this->passable
);
}
Then there is no then, so it's over all middleware, isn't it elegant?
Since the second parameter of Aray_reduce requires a function, we focus here to see 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 can be very dizzy, closure return closure. 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 by $next ($request) in the middle of the transfer process, the $next ($request) means that the closure is executed, that the closure is function A, and then returns function B, which can be passed on to the next middleware.
And then simplify the code:
Here the $stack is actually closure, the first traversal will be introduced into the $firstslice this closure, after each will be passed into the following function; And $pipe is each middleware
array_reduce ($pipes, function ($stack, $pipe) {return
function ($passable) use ($stack, $pipe) {
};
}, $firstSlice);
Look at this code again:
To determine if it is a closure, this is to determine whether the middleware form is closed, the words are executed directly and incoming $passable[request instances] and $stack[are passed to the next middleware closure, and return
if ($pipe instanceof Closure) {return
Call_user_func ($pipe, $passable, $stack);
When it's not a closure, it's like this. Illuminate\foundation\http\middleware\checkformaintenancemode execute
} else {
//parse, return name, this $ Parameters read for a long time the source code is still not understand, 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 Photo:
Each iteration passes in the last closure and the middleware that needs to be executed, because the array is inverted, based on the advanced features of the stack, middleware 3 is first packaged and the middleware 1 is on the outermost layer. Remember, arrary_reduce he does not implement 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
Copy Code code as follows:
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 handled by the previous middleware. So the process of the processing of the call_user_func is over, the understanding will be a bit around, as long as you remember the last is the most out of the outside to implement the middleware code
More interested in laravel related content readers can view the site topics: "Laravel Framework Introduction and Advanced Course", "PHP Excellent Development Framework Summary", "Smarty Template Primer Tutorial", "PHP date and Time usage summary", "PHP object-oriented Program Design Introductory Course ", PHP string (String) Usage summary," PHP+MYSQL Database operation Introduction Tutorial "and" PHP common database Operation Skills Summary "
I hope this article will help you with your PHP programming based on the Laravel framework.