Inhaltsverzeichnis
Middleware-Quellcode" >Middleware-Quellcode
" >Die laufende Implementierung von Pipeline
Pipeline小结" >Pipeline小结
Route中间件" >Route中间件
Controller后执行中间件" >Controller后执行中间件
如何使用中间件" >如何使用中间件
中间件小结" >中间件小结
Heim PHP-Framework Laravel Analyse des Middleware-Quellcodes basierend auf Laravel5.2

Analyse des Middleware-Quellcodes basierend auf Laravel5.2

Jul 31, 2018 pm 02:37 PM

In Laravel5.2 besteht die Hauptfunktion von HTTP darin, HTTP-Anfragen zu filtern (php aritsan hat keinen Middleware-Mechanismus) Es macht auch die Systemebene (HTTP-Filterebene) klarer sieht auch elegant aus. Der Code zur Implementierung der Middleware ist jedoch sehr kompliziert. Lassen Sie uns den Inhalt des Quellcodes der Middleware analysieren.

Middleware-Quellcode

Die Middleware selbst ist in zwei Typen unterteilt, einer für alle http und der andere für die Route. Ein Anforderungszyklus mit Middleware ist: Die Anforderung muss zuerst die Http-Middleware durchlaufen, bevor sie zum Router gehen kann, und dann die Route-Middleware und schließlich wird der entsprechende Controller-Code eingegeben. Laravel unterteilt Anfragen in zwei Typen: http und Konsole. Verschiedene Anforderungsmethoden verwenden ein eigenes , um Kernel anzusteuern. HTTP-Anfragen werden von der Klasse Application
gesteuert, die die gesamte Middleware definiert. Ihre übergeordnete Klasse IlluminateFoundationHttpKernel ist der Einstiegspunkt für die Verarbeitung von Anfragen IlluminateFoundationHttpKernel::handle

HTTP-Middleware

Wenn Sie die Eingabemethode

verfolgen, ist es leicht, die Funktion (handle()) zu finden: IlluminateFoundationHttpKernel::sendRequestThroughRouter

protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);

    Facade::clearResolvedInstance('request');

    $this->bootstrap();

    return (new Pipeline($this->app))
                ->send($request)
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                ->then($this->dispatchToRouter());
}
Nach dem Login kopieren

Diese Funktion verteilt Requset an den Router (Sie können es am Methodennamen erkennen), The Die Hauptlogik wird durch

vervollständigt, wodurch das Anforderungsset die Erkennung der HTTP-Middleware bestehen und dann den Router erreichen kann. Der Code hier sieht elegant aus, ist aber nicht sehr verständlich. Wenn Sie also den Funktionsmechanismus von IlluminateRoutingPipeline verstehen, verstehen Sie auch die Verwendung von Middleware. Pipeline

Die laufende Implementierung von Pipeline

Die Basisklasse ist Pipleline und ihre Ausführung erfolgt in der IlluminatePipelinePipeline-Methode: then

public function then(Closure $destination)
{
    $firstSlice = $this->getInitialSlice($destination);

    $pipes = array_reverse($this->pipes);

    return call_user_func(
        array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable
    );
}
Nach dem Login kopieren

Verstehen Sie dies: Um einen Code auszuführen, müssen Sie wissen, was array_reduce() tut. Um zu verstehen, wie

funktioniert, schreiben Sie zunächst array_reduce um: array_reduce

//将数组中的元素,依次执行$func函数,且上一次的$func的返回值作为下一次调用$func的第一个参数输入
function array_reduce_back($arr, callable $func, $firstResult = null)
{
    $result = $firstResult;
    
    foreach ($arr as $v) {
        $result = $func($result, $v);
    }
    
    return $result;
}
Nach dem Login kopieren

Daher lautet das

im Quellcode $func und es wird eine Rückruffunktion zurückgegeben: getSlice() (function($passable) use ($stack, $pipe){...} und $stack werden durch die eingegebenen spezifischen Werte ersetzt, das heißt, der erste Parameter, der als letztes Rückgabeergebnis in die nächste $pipe eingegeben wird, ist die oben erwähnte Rückruffunktion Die Array-Durchquerung ist abgeschlossen. $funcWas zurückgegeben wird, ist eine Rückruffunktion. Der Schlüssel liegt nun darin, zu verstehen, wie diese Rückruffunktion aussieht und wie sie ausgeführt wird. Um die Diskussion zu erleichtern, kann der folgende Code analysiert werden: array_reduce

call_user_func(
        array_reduce([1, 2, 3], $this->getSlice(), $firstSlice), $this->passable
    );
Nach dem Login kopieren

Analyse des Middleware-Quellcodes basierend auf Laravel5.2

Ausführungsanweisungen:

1
ist der initialisierte Wert, also $result_0 ist, < Der Rückruf von 🎜>$firstSlice2. Jedes Mal, wenn ein Element durchlaufen wird, wird der Rückruf von IlluminatePipelinePipeline::getInitialSlice ausgeführt und ein Rückruf
wird ebenfalls zurückgegeben. 3. Der spezifische Ausführungscode in IlluminatePipelinePipeline::getSlice ist in
$result4. Das endgültige getSlice()-Rückgabeergebnis ist
, eine mehrschichtige Abschluss-Callback-Funktion array_reduce 5. Was ausgeführt wird, ist $result_3, also
call_user_func($result_3, $this->passable)function($this->passable) use ($result_2, 3){...} wurde ausgeführt. Da wir nun wissen, wie

funktioniert, müssen wir herausfinden, wie die Rückruffunktion ausgeführt wird. Folgen Sie nun dem

in then() um zu sehen, wie es ausgeführt wird. sendRequestThroughRouter

// 把具体的参数带进来
return (new Pipeline($this->app))
                ->send($request)
                ->through([&#39;\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode&#39;])
                ->then($this->dispatchToRouter());
Nach dem Login kopieren
PipelineUnter Verwendung des oben analysierten

-Ausführungsprozesses wird bald analysiert, dass die letzte Ausführung

function($requset) use (\Illuminate\Foundation\Http\Kernel::dispatchToRouter(), &#39;\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode&#39;) {

            if ($pipe instanceof Closure) {
                return call_user_func($pipe, $passable, $stack);
            }
            
            // $name和$parameters很容易得到
            // $name = &#39;\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode&#39;;
            // $parameters = [];
            list($name, $parameters) = $this->parsePipeString($pipe);


            // 执行的就是\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::handle($request, \Illuminate\Foundation\Http\Kernel::dispatchToRouter())
            return call_user_func_array([$this->container->make($name), $this->method],
                        array_merge([$passable, $stack], $parameters));
}
Nach dem Login kopieren
PipelineDie logische Verarbeitung ist angekommen

und ihr Code lautet:

public function handle($request, Closure $next)
{
    if ($this->app->isDownForMaintenance()) {
        throw new HttpException(503);
    }

    return $next($request);
}
Nach dem Login kopieren
IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::handleHier verarbeitet es die von dieser Middleware geforderten Filterbedingungen und führt gleichzeitig

aus, d. h.

Auf diese Weise wird die Anfrage an den Router und alle Http Die Verarbeitungsarbeit der Middleware ist abgeschlossen, und $next($request) ist ein unverzichtbarer Vorgang für jede Middleware, da der Rückruf im Rückruf verschachtelt ist, was bedeutet, dass die Middleware IlluminateFoundationHttpKernel::dispatchToRouter() an den nächsten Rückruf weitergibt und an den nächsten analysiert wird Middleware-Stücke bis zum letzten. Folgen Sie dem oben analysierten $next($request)-Ausführungsprozess und schließen Sie ihn ab: RequestPipeline6. Führen Sie den Rückruf in $result_3 aus,

instanziieren Sie die Middleware, führen Sie sie aus

, führen Sie den Rückruf während der Verarbeitung aus getSlicehandle 7. Wenn im Rückruf verschachtelte Rückrufe vorhanden sind, muss jede Middleware über den Code zum Ausführen des Rückrufs verfügen

, um sicherzustellen, dass die Rückrufe im Rückruf ausgeführt werden. Die Ausführungsreihenfolge ist 3 ::. handel, 2::handel, 1::handel, $first

8.最里面一层,一定是传递给then()的参数,then执行的就是最后一步

9.执行的顺序是由数组中的最后一个,向前,到then()的参数,为了使其执行顺序是数组中的第一个到最后一个,再到then()中的参数,then()方法中就做了一个反转array_reverse

Pipeline小结

现在,Pipeline的所有执行流程就都分析完了。实现代码真的很绕,但理解之后编写自定义的中间件应该就很容易了。现在再把Pipeline的使用翻译成汉语,应该是这样的

// 使用管道,发送$request,使之通过middleware ,再到$func
(new Pipeline($this->app))->send($request)->through($this->middleware)->then($func);
Nach dem Login kopieren

这样的代码不管是从语义上,还是使用上都很优雅,高!确实是高!再回到源码,Requset的流程就通过dispatchToRouter进入到了Router

Route中间件

在Router中,\Illuminate\Routing\Router::dispatch就承接了来自Http中间件的Requset, Router把Request分发到了具体的Route,再进行处理,主要代码如下:

public function dispatchToRoute(Request $request)
{
    // 找到具体的路由对象,过程略
    $route = $this->findRoute($request);

    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    // 执行Request匹配到Route的事件,具体的代码在这里:\Illuminate\Foundation\Providers\FoundationServiceProvider::configureFormRequests
    $this->events->fire(new Events\RouteMatched($route, $request));
    
    // 这里就运行路由中间件了
    $response = $this->runRouteWithinStack($route, $request);

    return $this->prepareResponse($request, $response);
}


protected function runRouteWithinStack(Route $route, Request $request)
{
    // 获取该路由上的中间件
    // 简单就点可这样写:
    // $middleware = App::shouldSkipMiddleware() ? [] : $this->gatherRouteMiddlewares($route);
    $shouldSkipMiddleware = $this->container->bound(&#39;middleware.disable&#39;) &&
                         $this->container->make(&#39;middleware.disable&#39;) === true;

    $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddlewares($route);
    
    // 了解Pipeline后,这里就好理解了,应该是通过管道,发送$request,经过$middleware,再到then中的回调
    return (new Pipeline($this->container))
                    ->send($request)
                    ->through($middleware)
                    ->then(function ($request) use ($route) {
                        return $this->prepareResponse(
                            $request,
                            $route->run($request)
                        );
                    });
}
Nach dem Login kopieren

如何获取Route中间件的,就可以跟gatherRouteMiddlewares,这个代码并不难,很好跟。接下来,Request就到到达至于Controller, Request是如何到达Controller的代码就不难了,这里就不说了

Controller后执行中间件

成功获取Response后,在public/index.php58行执行了$kernel->terminate($request, $response);, 也就是在主要逻辑处理完成之后,再执行此代码,它实际上调用是的\Illuminate\Foundation\Http\Kernel::terminate, 跟进去就很容易发现,它处理了这此请求所涉及到的中间件,并执行了各自的terminate方法,到这里,中间件的另一个功能就展现出来了,就是主要逻辑完成之后的收尾工作.到这里为止,中间件就完成了它的使命(一个请求也就完成了)

如何使用中间件

在官方文档上讲解的很清楚注册中间

中间件小结

至此,中间件的实现逻辑与使用就清晰了.从执行的顺序来分,一个在Controller之前,一个在Controller之后,所以它一个很重要的作用就是可以让Controller专注于自己的主要逻辑的职责更明确. 奇怪的是,但前后两种中间件的执行方式却不一样, \Illuminate\Foundation\Http\Kernel::terminate,中间件的结束却没有使用Pipeline, 而是直接foreach.相同的工作却用两种代码来实现.现在看来,中间件本身并不复杂,但它带给了我两个启发,1.层次明确 2,Pipeline所带来的优雅.

相关推荐:

laravel5.4中自定义包开发的实例

Laravel 5.1框架中如何创建自定义Artisan控制台命令

laravel框架的启动过程分析

Das obige ist der detaillierte Inhalt vonAnalyse des Middleware-Quellcodes basierend auf Laravel5.2. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was ist besser, Django oder Laravel? Was ist besser, Django oder Laravel? Mar 28, 2025 am 10:41 AM

Sowohl Django als auch Laravel sind Full-Stack-Frameworks. Django eignet sich für Python -Entwickler und komplexe Geschäftslogik, während Laravel für PHP -Entwickler und elegante Syntax geeignet ist. 1.Django basiert auf Python und folgt der "batteriebetriebenen" Philosophie, die für schnelle Entwicklung und hohe Parallelität geeignet ist. 2. Laravel basiert auf PHP, der die Entwicklererfahrung betont und für kleine bis mittlere Projekte geeignet ist.

Laravel und das Backend: Logik der Webanwendungen mit Strom versorgen Laravel und das Backend: Logik der Webanwendungen mit Strom versorgen Apr 11, 2025 am 11:29 AM

Wie spielt Laravel eine Rolle in der Backend -Logik? Es vereinfacht und verbessert die Backend -Entwicklung durch Routing -Systeme, eloquentorm, Authentifizierung und Autorisierung, Ereignis und Zuhörer sowie Leistungsoptimierung. 1. Das Routing -System ermöglicht die Definition der URL -Struktur und die Anforderungsverarbeitungslogik. 2.Loquentorm vereinfacht die Datenbankinteraktion. 3. Das Authentifizierungs- und Autorisierungssystem ist für die Benutzerverwaltung geeignet. 4. Die Ereignis und der Hörer implementieren locker gekoppelte Codestruktur. 5. Leistungsoptimierung verbessert die Anwendungseffizienz durch Zwischenspeicherung und Warteschlange.

Welches ist besser PHP oder Laravel? Welches ist besser PHP oder Laravel? Mar 27, 2025 pm 05:31 PM

PHP und Laravel sind nicht direkt vergleichbar, da Laravel ein PHP-basierter Framework ist. 1.PHP ist für kleine Projekte oder schnelle Prototypen geeignet, da es einfach und direkt ist. 2. Laravel ist für große Projekte oder effiziente Entwicklung geeignet, da es umfangreiche Funktionen und Werkzeuge bietet, aber eine steile Lernkurve aufweist und möglicherweise nicht so gut ist wie reines PHP.

Ist Laravel ein Frontend oder ein Backend? Ist Laravel ein Frontend oder ein Backend? Mar 27, 2025 pm 05:31 PM

LaravelisabackendFrameworkBuiltonPhp, entworfene WebApplicationDevelopment.itfocuseSonserver-Sidelogic, DatabaSemanagement und Applicationsstruktur und CanBeintegratedWithFrontendTechnologies-ähnlich.

Beispiel für Laravel -Einführung Beispiel für Laravel -Einführung Apr 18, 2025 pm 12:45 PM

Laravel ist ein PHP -Framework zum einfachen Aufbau von Webanwendungen. Es bietet eine Reihe leistungsstarker Funktionen, darunter: Installation: Installieren Sie die Laravel CLI weltweit mit Komponisten und erstellen Sie Anwendungen im Projektverzeichnis. Routing: Definieren Sie die Beziehung zwischen der URL und dem Handler in Routen/Web.php. Ansicht: Erstellen Sie eine Ansicht in Ressourcen/Ansichten, um die Benutzeroberfläche der Anwendung zu rendern. Datenbankintegration: Bietet eine Out-of-the-Box-Integration in Datenbanken wie MySQL und verwendet Migration, um Tabellen zu erstellen und zu ändern. Modell und Controller: Das Modell repräsentiert die Datenbankentität und die Controller -Prozesse HTTP -Anforderungen.

Laravels Vielseitigkeit: Von einfachen Standorten zu komplexen Systemen Laravels Vielseitigkeit: Von einfachen Standorten zu komplexen Systemen Apr 13, 2025 am 12:13 AM

Das Laravel -Entwicklungsprojekt wurde aufgrund seiner Flexibilität und Kraft ausgewählt, um den Bedürfnissen unterschiedlicher Größen und Komplexität zu entsprechen. Laravel bietet Routing-System, eloquentorm, Artisan Command Line und andere Funktionen und unterstützt die Entwicklung von einfachen Blogs bis hin zu komplexen Systemen auf Unternehmensebene.

Wie man laravel lernt wie man laravel kostenlos lernt Wie man laravel lernt wie man laravel kostenlos lernt Apr 18, 2025 pm 12:51 PM

Möchten Sie das Laravel -Rahmen lernen, aber unter keinen Ressourcen oder dem wirtschaftlichen Druck leiden? Dieser Artikel bietet Ihnen ein kostenloses Lernen von Laravel und lehrt Sie, wie Sie Ressourcen wie Online -Plattformen, Dokumente und Community -Foren verwenden, um eine solide Grundlage für Ihre PHP -Entwicklungsreise zu schaffen.

Warum ist Laravel so beliebt? Warum ist Laravel so beliebt? Apr 02, 2025 pm 02:16 PM

Die Popularität von Laravel umfasst seinen vereinfachten Entwicklungsprozess, eine angenehme Entwicklungsumgebung und umfangreiche Merkmale. 1) Es absorbiert die Designphilosophie von RubyonRails und kombiniert die Flexibilität von PHP. 2) Bereitstellung von Werkzeugen wie eloquentorm, Blade Template Engine usw. zur Verbesserung der Entwicklungseffizienz. 3) Sein MVC -Architektur- und Abhängigkeitsinjektionsmechanismus macht den Code modularer und prüfbarer. 4) Bietet leistungsstarke Debugging -Tools und Leistungsoptimierungsmethoden wie Caching -Systeme und Best Practices.

See all articles