Wie wird die Middleware von Laravel implementiert? In diesem Artikel wird hauptsächlich das Implementierungsprinzip der Laravel-Middleware vorgestellt und die Konzepte, Prinzipien, zugehörigen Methoden und Verwendungsfähigkeiten der Laravel-Middleware ausführlicher analysiert. Freunde in Not können sich darauf beziehen. Ich hoffe, es hilft allen.
Die Details lauten wie folgt:
#1 Was ist Middleware?
Bei einer Webanwendung können wir vor der tatsächlichen Verarbeitung einer Anfrage verschiedene Beurteilungen der Anfrage vornehmen, bevor sie an eine tiefere Ebene weitergeleitet werden kann. Und wenn wir if else wie dieses verwenden, wird es schwieriger, den Code zu warten, sobald immer mehr Bedingungen beurteilt werden müssen, und die Kopplung zwischen Systemen wird zunehmen, und Middleware kann dieses Problem lösen. Wir können diese Urteile in Middleware aufteilen, die Anfragen leicht filtern kann.
#2 Middleware in Laravel
In Laravel basiert die Implementierung von Middleware tatsächlich auf der Implementierung der IlluminatePipelinePipeline-Klasse. Schauen wir uns zunächst das Auslösen des Middleware-Dateicodes an. Es ist ganz einfach: Übergeben Sie die Anfrage nach der Bearbeitung einfach an einen Abschluss und leiten Sie sie dann weiter.
public function handle($request, Closure $next) { //do something for $request return $next($request); }
#3 Interne Implementierung von Middleware
Wie oben erwähnt, wird Middleware von Pipeline implementiert und ihr Aufruf erfolgt in IlluminateRoutingRouter
return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function ($request) use ($route) { return $this->prepareResponse( $request, $route->run($request) ); });
Wie Sie sehen können, ruft der Middleware-Ausführungsprozess drei Methoden auf. Werfen wir einen Blick auf die Codes dieser drei Methoden:
Sendemethode
public function send($passable){ $this->passable = $passable; return $this; }
Tatsächlich macht die Sendemethode nichts, sie setzt nur die Notwendigkeit, das Wasser in die Middleware zu leiten. Das verarbeitete Objekt ist in diesem Fall die HTTP-Anforderungsinstanz.
Through-Methode
public function through($pipes){ $this->pipes = is_array($pipes) ? $pipes : func_get_args(); return $this; }
Die Through-Methode ist ebenfalls sehr einfach, nämlich die zu verarbeitende Middleware-Verarbeitung festzulegen.
then-Methode
Hier kommt der wirklich schwierige Teil. Der Code der then-Methode ist sehr prägnant, aber nicht leicht zu verstehen.
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 ); }
Dann wird die gesamte Middleware nicht weitergegeben.
Da der zweite Parameter von aray_reduce eine Funktion erfordert, konzentrieren wir uns hier auf den Quellcode der getSlice()-Methode
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)); } }; }; }
Es kann sein, dass Ihnen schwindelig wird, wenn Sie sehen, dass „Closure“ den Abschluss zurückgibt . Zur Vereinfachung gibt getSlice() eine Funktion A zurück und Funktion A gibt Funktion B zurück. Warum zwei Funktionen zurückgeben? Weil wir $next($request) verwenden, um das Objekt während des Übertragungsprozesses zu übergeben, und $next($request) bedeutet, dass der Abschluss ausgeführt wird. Dieser Abschluss ist Funktion A und gibt dann Funktion B zurück, an die übergeben werden kann die nächste Middleware.
Lassen Sie uns den Code noch einmal vereinfachen:
//这里的$stack其实就是闭包,第一次遍历的时候会传入$firstSlice这个闭包,以后每次都会传入下面的那个function; 而$pipe就是每一个中间件 array_reduce($pipes, function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { }; }, $firstSlice);
Sehen Sie sich diesen Code noch einmal an:
//判断是否为闭包,这里就是判断中间件形式是不是闭包,是的话直接执行并且传入$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)); }
Sehen Sie sich ein anderes Bild an:
Jede Iteration übergibt den vorherigen Abschluss und die auszuführende Middleware. Da das Array umgekehrt ist und auf der First-In-Last-Out-Funktion des Stapels basiert, wird Middleware 3 zuerst gepackt Die Middleware 1 befindet sich auf der äußersten Schicht. Denken Sie daran, dass array_reduce keinen Middleware-Code ausführt, sondern Middleware umschließt.
Nachdem Sie das gesehen haben, sollten Sie verstehen, dass array_reduce irgendwann func3 zurückgibt, dann ist call_user_func(func3,$this->passable) tatsächlich
return call_user_func($middleware[0]-> handle, $this->passable, func2);
Und der Handle-Code in unserer Middleware lautet:
public function handle($request, Closure $next) { return $next($request); }
Dies entspricht der Rückgabe von func2($request), hier dem $ Die Anfrage wird von der vorherigen Middleware verarbeitet. Der Zhengguo-Middleware-Prozess ist also abgeschlossen und es ist etwas verwirrend, ihn zu verstehen. Denken Sie daran, dass der äußerste call_user_func am Ende den Middleware-Code ausführt
Verwandte Empfehlungen:
Laravel optimierte Split-Routing-Datei
Laravel verwendet das Pagination-Plug-in, um benutzerdefiniertes Paging zu implementieren
Laravel schreibt APP-Schnittstelle (API)
Das obige ist der detaillierte Inhalt vonEntdecken Sie, wie die Middleware von Laravel implementiert wird. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!