Explore how Laravel's middleware is implemented
How is Laravel's middleware implemented? This article mainly introduces the implementation principle of Laravel middleware, and analyzes the concepts, principles, related methods and usage skills of Laravel middleware in more detail. Friends in need can refer to it. I hope to be helpful.
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. And if we use if else like this, once more and more conditions need to be judged, it will make the code more difficult to maintain, and the coupling between systems will increase, and middleware can solve this problem. We can separate these judgments into middleware, which can easily filter requests.
#2 Middleware in Laravel
In Laravel, the implementation of middleware actually depends on the Illuminate\Pipeline\Pipeline class. Let’s do it first. Take a look at the code that triggers the middleware. It's very simple, just transfer the request to a closure after processing and then continue passing it on.
public function handle($request, Closure $next) { //do something for $request return $next($request); }
#3 Internal implementation of middleware
As mentioned above, 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 codes of these three methods:
send method
public function send($passable){ $this->passable = $passable; return $this; }
In fact, the send method does nothing, it just sets the requirements that need to be pipelined in the middleware. The object, in this case, 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, which is to set the middleware processing that needs to be processed.
then method
The really difficult thing to understand is here. The then method code is very concise, but it is not easy to understand.
public function then(Closure $destination){ //then方法接受一个闭包作为参数,然后经过getInitialSlice包装,而getInitialSlice返回的其实也是一个闭包,如果还不知道什么是闭包先去看PHP文档 $firstSlice = $this->getInitialSlice($destination); //反转中间件数组,主要是利用了栈的特性,用处接下来再说 $pipes = array_reverse($this->pipes); //这个call_user_func先不要看,它其实就是执行了一个array_reduce返回的闭包 return call_user_func( //接下来用array_reduce来用回调函数处理数组,建议先去PHP文档读懂array_reduce的执行原理。其实arrary_reduce什么事情都没干,就是包装闭包然后移交给call_user_func来执行 array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable ); }
Then there is no more, so all the middleware is passed. Isn’t it very elegant?
Since the second parameter of aray_reduce requires a function, let’s focus on the source code of the getSlice() method.
protected function getSlice(){ return function ($stack, $pipe) { //这里$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)); } }; }; }
You may feel dizzy when you see it. Closure returns closure. To simplify it, getSlice() returns a function A, and function A returns function B. Why return two functions? Because we use $next($request) to pass the object during the transfer process, and $next($request) means that the closure is executed. This closure is function A, and then returns function B. , which can be passed to the next middleware.
Let’s simplify the code again:
//这里的$stack其实就是闭包,第一次遍历的时候会传入$firstSlice这个闭包,以后每次都会传入下面的那个function; 而$pipe就是每一个中间件 array_reduce($pipes, function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { }; }, $firstSlice);
Look at this code again:
//判断是否为闭包,这里就是判断中间件形式是不是闭包,是的话直接执行并且传入$passable[请求实例]和$stack[传递给下一个中间件的闭包],并且返回 if ($pipe instanceof Closure) { return call_user_func($pipe, $passable, $stack); //不是闭包的时候就是形如这样Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode执行 } else { //解析,把名称返回,这个$parameters看了许久源码还是看不懂,应该是和参数相关,不过不影响我们的分析 list($name, $parameters) = $this->parsePipeString($pipe); //从容器中解析出中间件实例并且执行handle方法 return call_user_func_array([$this->container->make($name), $this->method], //$passable就是请求实例,而$stack就是传递的闭包 array_merge([$passable, $stack], $parameters)); }
Look at another picture:
Each iteration passes in the previous closure and the middleware that needs to be executed. Since the array is reversed and based on the first-in-last-out feature of the stack, middleware 3 is packaged first, and middleware 1 is at the end. Outer layer. Remember, array_reduce does not execute middleware code, but wraps middleware.
You should understand after seeing this, array_reduce will eventually return 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 by the previous middleware. So the process of Zhengguo middleware is over, and it will be a bit confusing to understand. Just remember that in the end, the outermost call_user_func executes the middleware code
Related recommendations:
Laravel optimization split routing file
Laravel uses the Pagination plug-in to implement custom paging
laravel writing APP interface (API)
The above is the detailed content of Explore how Laravel's middleware is implemented. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



The latest versions of Laravel 9 and CodeIgniter 4 provide updated features and improvements. Laravel9 adopts MVC architecture and provides functions such as database migration, authentication and template engine. CodeIgniter4 uses HMVC architecture to provide routing, ORM and caching. In terms of performance, Laravel9's service provider-based design pattern and CodeIgniter4's lightweight framework give it excellent performance. In practical applications, Laravel9 is suitable for complex projects that require flexibility and powerful functions, while CodeIgniter4 is suitable for rapid development and small applications.

For beginners, CodeIgniter has a gentler learning curve and fewer features, but covers basic needs. Laravel offers a wider feature set but has a slightly steeper learning curve. In terms of performance, both Laravel and CodeIgniter perform well. Laravel has more extensive documentation and active community support, while CodeIgniter is simpler, lightweight, and has strong security features. In the practical case of building a blogging application, Laravel's EloquentORM simplifies data manipulation, while CodeIgniter requires more manual configuration.

When choosing a framework for large projects, Laravel and CodeIgniter each have their own advantages. Laravel is designed for enterprise-level applications, offering modular design, dependency injection, and a powerful feature set. CodeIgniter is a lightweight framework more suitable for small to medium-sized projects, emphasizing speed and ease of use. For large projects with complex requirements and a large number of users, Laravel's power and scalability are more suitable. For simple projects or situations with limited resources, CodeIgniter's lightweight and rapid development capabilities are more ideal.

Laravel - Artisan Commands - Laravel 5.7 comes with new way of treating and testing new commands. It includes a new feature of testing artisan commands and the demonstration is mentioned below ?

For small projects, Laravel is suitable for larger projects that require strong functionality and security. CodeIgniter is suitable for very small projects that require lightweight and ease of use.

Comparing Laravel's Blade and CodeIgniter's Twig template engine, choose based on project needs and personal preferences: Blade is based on MVC syntax, which encourages good code organization and template inheritance. Twig is a third-party library that provides flexible syntax, powerful filters, extended support, and security sandboxing.

Laravel - Artisan Console - Laravel framework provides three primary tools for interaction through command-line namely: Artisan, Ticker and REPL. This chapter explains about Artisan in detail.

Laravel - Pagination Customizations - Laravel includes a feature of pagination which helps a user or a developer to include a pagination feature. Laravel paginator is integrated with the query builder and Eloquent ORM. The paginate method automatical
