Heim PHP-Framework Denken Sie an PHP Implementierungsanalyse des ThinkPHP6.0-Pipeline-Modus und der Middleware

Implementierungsanalyse des ThinkPHP6.0-Pipeline-Modus und der Middleware

Nov 04, 2019 pm 01:29 PM
thinkphp

Erklärung

ThinkPHP 6.0 RC5 begann, den Pipeline-Modus zur Implementierung von Middleware zu verwenden, der präziser und geordneter ist als die Implementierung früherer Versionen. In diesem Artikel werden die Implementierungsdetails analysiert.

Zuerst beginnen wir mit der Eintragsdatei public/index.php, $http = (new App())->http;

Besorgen Sie sich eine Instanz der http-Klasse und rufen Sie deren Ausführung auf Methode :$response = $http->run(); und dann ruft ihre Ausführungsmethode die runWithRequest-Methode auf:

protected function runWithRequest(Request $request)
{
    .
    .
    .
    return $this->app->middleware->pipeline()
        ->send($request)
        ->then(function ($request) {
            return $this->dispatchToRoute($request);
        });
}
Nach dem Login kopieren

Die Ausführung der Middleware erfolgt in der endgültigen Return-Anweisung.

Pipeline, Through, Sendemethode

$this->app->middleware->pipeline() 的 pipeline 方法:
public function pipeline(string $type = 'global')
{
    return (new Pipeline())  
           // array_map将所有中间件转换成闭包,闭包的特点:
          // 1. 传入参数:$request,请求实例; $next,一个闭包
          // 2. 返回一个Response实例
        ->through(array_map(function ($middleware) {
            return function ($request, $next) use ($middleware) {
                list($call, $param) = $middleware;
                if (is_array($call) && is_string($call[0])) {
                    $call = [$this->app->make($call[0]), $call[1]];
                }
                 // 该语句执行中间件类实例的handle方法,传入的参数是外部传进来的$request和$next
                 // 还有一个$param是中间件接收的参数
                $response = call_user_func($call, $request, $next, $param);
                if (!$response instanceof Response) {
                    throw new LogicException('The middleware must return Response instance');
                }
                return $response;
            };
            // 将中间件排序
        }, $this->sortMiddleware($this->queue[$type] ?? [])))
        ->whenException([$this, 'handleException']);
}
Nach dem Login kopieren

through-Methodencode:

public function through($pipes)
{
    $this->pipes = is_array($pipes) ? $pipes : func_get_args();
    return $this;
}
Nach dem Login kopieren

Der vorherige Aufruf von Through ist der eingehende array_map (...) kapselt die Middleware in Abschlüsse und speichert diese Abschlüsse im Attribut $pipes der Pipeline-Klasse.

Signatur der array_map-Methode von PHP:

array_map ( callable $callback , array $array1 [, array $... ] ) : array
Nach dem Login kopieren

$callback iteriert über jedes Element von $array und gibt einen neuen Wert zurück. Daher lauten die endgültigen formalen Merkmale jedes Abschlusses in $pipes wie folgt (Pseudocode):

function ($request, $next) {
    $response = handle($request, $next, $param);
    return $response;
}
Nach dem Login kopieren
Nach dem Login kopieren

Dieser Abschluss empfängt zwei Parameter, einer ist die Anforderungsinstanz und der andere ist die Rückruffunktion, Handle-Methode Nach der Verarbeitung , wird die Antwort abgerufen und zurückgegeben.

through gibt eine Instanz der Pipeline-Klasse zurück und ruft dann die Sendemethode auf:

public function send($passable)
{
    $this->passable = $passable;
    return $this;
}
Nach dem Login kopieren

Diese Methode ist sehr einfach. Sie speichert lediglich die eingehende Anforderungsinstanz in der $passable-Mitgliedsvariablen gibt schließlich die Instanz der Pipeline-Klasse zurück, sodass andere Methoden der Pipeline-Klasse in einer Kette aufgerufen werden können.

dann, nach der Carry-Methode

send-Methode, dann die then-Methode aufrufen:

return $this->app->middleware->pipeline()
            ->send($request)
            ->then(function ($request) {
                return $this->dispatchToRoute($request);
            });
Nach dem Login kopieren

The then erhält hier einen Abschluss als Parameter. Dieses Abschlusspaket enthält tatsächlich den Ausführungscode für die Controller-Operationen.

dann Methodencode:

public function then(Closure $destination)
{
    $pipeline = array_reduce(
        //用于迭代的数组(中间件闭包),这里将其倒序
        array_reverse($this->pipes),
        // array_reduce需要的回调函数
        $this->carry(),
        //这里是迭代的初始值
        function ($passable) use ($destination) {
            try {
                return $destination($passable);
            } catch (Throwable | Exception $e) {
                return $this->handleException($passable, $e);
            }
        });
    return $pipeline($this->passable);
}
Nach dem Login kopieren

Carry-Code:

protected function carry()
{
    // 1. $stack 上次迭代得到的值,如果是第一次迭代,其值是后面的「初始值
    // 2. $pipe 本次迭代的值
    return function ($stack, $pipe) {
        return function ($passable) use ($stack, $pipe) {
            try {
                return $pipe($passable, $stack);
            } catch (Throwable | Exception $e) {
                return $this->handleException($passable, $e);
            }
        };
    };
}
Nach dem Login kopieren

Um die Analyse des Prinzips zu erleichtern, Wir fügen die Carry-Methode ein. Verbinden Sie sie mit dann und entfernen Sie den Fehlerabfangcode, um Folgendes zu erhalten:

public function then(Closure $destination)
{
    $pipeline = array_reduce(
        array_reverse($this->pipes),
        function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                return $pipe($passable, $stack);
            };
        },
        function ($passable) use ($destination) {
            return $destination($passable);
        });
    return $pipeline($this->passable);
}
Nach dem Login kopieren

Der Schlüssel hier ist, den Ausführungsprozess von array_reduce und $pipeline($this->passable These) zu verstehen Zwei Vorgänge können mit „Zwiebeln einwickeln“ und „Zwiebeln schälen“ verglichen werden.

Die erste Iteration von array_reduce, der Anfangswert von $stack ist:

(A) Der Rückgabewert der Rückruffunktion

function ($passable) use ($destination) {
    return $destination($passable);
});
Nach dem Login kopieren

ist :

(B)

function ($passable) use ($stack, $pipe) {
    return $pipe($passable, $stack);
};
Nach dem Login kopieren

Das Einsetzen von A in B kann den Wert von $stack nach der ersten Iteration erhalten:

(C )

function ($passable) use ($stack, $pipe) {
    return $pipe($passable, 
        function ($passable) use ($destination) {
            return $destination($passable);
        })
    );
};
Nach dem Login kopieren

Ersetzen Sie für die zweite Iteration auf ähnliche Weise C in B, um Folgendes zu erhalten:

(D)

// 伪代码
// 每一层的$pipe都代表一个中间件闭包
function ($passable) use ($stack, $pipe) {
    return $pipe($passable,  //倒数第二层中间件
        function ($passable) use ($stack, $pipe) {
            return $pipe($passable,  //倒数第一层中间件
                function ($passable) use ($destination) {
                    return $destination($passable);  //包含控制器操作的闭包
                })
            );
        };
    );
};
Nach dem Login kopieren

Und so weiter , wir ersetzen so viele Middlewares, wie Sie möchten, und wenn Sie $stack das letzte Mal erhalten, geben Sie es an $pipeline zurück. Da die Middleware-Verschlüsse in der vorherigen Reihenfolge umgekehrt wurden, werden die Verschlüsse vorne in die innere Schicht eingewickelt, sodass die Verschlüsse nach der umgekehrten Reihenfolge später außen liegen und aus der Perspektive der positiven Reihenfolge zu den früheren werden . Middleware ist die äußerste Schicht.

Nachdem wir die Verschlüsse Schicht für Schicht umwickelt haben, erhalten wir einen „Super“-Verschluss D ähnlich einer Zwiebelstruktur. Die Struktur dieses Verschlusses ist wie in den Codekommentaren oben dargestellt. Übergeben Sie abschließend das $request-Objekt an diesen Abschluss und führen Sie ihn aus: $pipeline($this->passable);, wodurch ein Vorgang ähnlich dem Schälen einer Zwiebel gestartet wird. Als nächstes wollen wir sehen, wie die Zwiebel geschält wird.

Analyse des Zwiebelschälprozesses

array_map(...) Verarbeiten Sie jede Middleware-Klasse zu einem Abschluss mit einer Struktur ähnlich dieser:

function ($request, $next) {
    $response = handle($request, $next, $param);
    return $response;
}
Nach dem Login kopieren
Nach dem Login kopieren

Der Griff ist der Eingang zur Middleware und seine strukturellen Eigenschaften sind wie folgt:

public function handle($request, $next, $param) {
    // do sth ------ M1-1 / M2-1
    $response = $next($request);
    // do sth ------ M1-2 / M2-2
    return $response;
}
Nach dem Login kopieren

Die „Zwiebel“ über uns hat insgesamt nur zwei Schichten, das heißt, es gibt zwei Schichten von Middleware-Verschlüssen, vorausgesetzt M1-1 und M1-2 sind die Präfix- bzw. Postwert-Operationspunkte der ersten Middleware-Handle-Methode. Dasselbe gilt für die zweite Middleware, nämlich M2-1 und M2-2. Lassen Sie das Programm nun $pipeline($this->passable) ausführen, erweitern Sie es, d. h. führen Sie Folgendes aus:

// 伪代码
function ($passable) use ($stack, $pipe) {
    return $pipe($passable,  
        function ($passable) use ($stack, $pipe) {
            return $pipe($passable,  
                function ($passable) use ($destination) {
                    return $destination($passable);  
                })
            );
        };
    );
}($this->passable)
Nach dem Login kopieren

Zu diesem Zeitpunkt benötigt das Programm den Rückgabewert von:

return $pipe($passable,  
    function ($passable) use ($stack, $pipe) {
        return $pipe($passable,  
            function ($passable) use ($destination) {
                return $destination($passable);  
            })
        );
    };
);
Nach dem Login kopieren

, das heißt Um den ersten Middleware-Abschluss auszuführen, entspricht $passable dem $request-Parameter der Handle-Methode und der Abschluss der nächsten Ebene

function ($passable) use ($stack, $pipe) {
    return $pipe($passable,  
        function ($passable) use ($destination) {
            return $destination($passable);  
        })
    );
}
Nach dem Login kopieren

entspricht dem $next-Parameter der Handle-Methode.

Um den ersten Abschluss auszuführen, dh die Handle-Methode des ersten Abschlusses auszuführen, ist der Prozess wie folgt: Führen Sie zuerst den Code an Punkt M1-1 aus, dh die Voroperation, und führen Sie ihn dann aus $response = $next($request);, dann tritt das Programm ein, um den nächsten Abschluss auszuführen, $next($request) wird erweitert, das heißt:

function ($passable) use ($stack, $pipe) {
    return $pipe($passable,  
        function ($passable) use ($destination) {
            return $destination($passable);  
        })
    );
}($request)
Nach dem Login kopieren

und so weiter, führt den Abschluss aus, das heißt , führe die zweite aus Die Handle-Methode der Middleware führt zu diesem Zeitpunkt zuerst den M2-1-Punkt aus und führt dann $response = $next($request) aus. Der $next-Abschluss lautet zu diesem Zeitpunkt:

function ($passable) use ($destination) {
    return $destination($passable);  
})
Nach dem Login kopieren

Gehört zum Kern der Zwiebel – – Die innerste Schicht, die den Abschluss mit den Controller-Operationen darstellt, wird erweitert, um Folgendes anzuzeigen:

function ($passable) use ($destination) {
    return $destination($passable);  
})($request)
Nach dem Login kopieren

最终,我们从 return $destination($passable) 中返回一个 Response 类的实例,也就是,第二层的 $response = $next($request) 语句成功得到了结果,接着执行下面的语句,也就是 M2-2 点位,最后第二层闭包返回结果,也就是第一层闭包的 $response = $next($request) 语句成功得到了结果,然后执行这一层闭包该语句后面的语句,即 M1-2 点位,该点位之后,第一层闭包也成功返回结果,于是,then 方法最终得到了返回结果。

整个过程过来,程序经过的点位顺序是这样的:M1-1→M2-1→控制器操作→M2-2→M1-2→返回结果。

总结

整个过程看起来虽然复杂,但不管中间件有多少层,只要理解了前后两层中间件的这种递推关系,洋葱是怎么一层层剥开又一层层返回的,来多少层都不在话下。

Das obige ist der detaillierte Inhalt vonImplementierungsanalyse des ThinkPHP6.0-Pipeline-Modus und der Middleware. 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)

So führen Sie das Thinkphp-Projekt aus So führen Sie das Thinkphp-Projekt aus Apr 09, 2024 pm 05:33 PM

Um das ThinkPHP-Projekt auszuführen, müssen Sie: Composer installieren, das Projektverzeichnis aufrufen und http://localhost:8000 aufrufen.

Es gibt mehrere Versionen von thinkphp Es gibt mehrere Versionen von thinkphp Apr 09, 2024 pm 06:09 PM

ThinkPHP verfügt über mehrere Versionen, die für verschiedene PHP-Versionen entwickelt wurden. Zu den Hauptversionen gehören 3.2, 5.0, 5.1 und 6.0, während Nebenversionen dazu dienen, Fehler zu beheben und neue Funktionen bereitzustellen. Die neueste stabile Version ist ThinkPHP 6.0.16. Berücksichtigen Sie bei der Auswahl einer Version die PHP-Version, die Funktionsanforderungen und den Community-Support. Für optimale Leistung und Support wird empfohlen, die neueste stabile Version zu verwenden.

So führen Sie thinkphp aus So führen Sie thinkphp aus Apr 09, 2024 pm 05:39 PM

Schritte zum lokalen Ausführen von ThinkPHP Framework: Laden Sie ThinkPHP Framework herunter und entpacken Sie es in ein lokales Verzeichnis. Erstellen Sie einen virtuellen Host (optional), der auf das ThinkPHP-Stammverzeichnis verweist. Konfigurieren Sie Datenbankverbindungsparameter. Starten Sie den Webserver. Initialisieren Sie die ThinkPHP-Anwendung. Greifen Sie auf die URL der ThinkPHP-Anwendung zu und führen Sie sie aus.

Was ist besser, Laravel oder Thinkphp? Was ist besser, Laravel oder Thinkphp? Apr 09, 2024 pm 03:18 PM

Leistungsvergleich von Laravel- und ThinkPHP-Frameworks: ThinkPHP schneidet im Allgemeinen besser ab als Laravel und konzentriert sich auf Optimierung und Caching. Laravel schneidet gut ab, aber für komplexe Anwendungen ist ThinkPHP möglicherweise besser geeignet.

Entwicklungsvorschläge: So verwenden Sie das ThinkPHP-Framework zur Implementierung asynchroner Aufgaben Entwicklungsvorschläge: So verwenden Sie das ThinkPHP-Framework zur Implementierung asynchroner Aufgaben Nov 22, 2023 pm 12:01 PM

„Entwicklungsvorschläge: So verwenden Sie das ThinkPHP-Framework zur Implementierung asynchroner Aufgaben“ Mit der rasanten Entwicklung der Internettechnologie stellen Webanwendungen immer höhere Anforderungen an die Verarbeitung einer großen Anzahl gleichzeitiger Anforderungen und komplexer Geschäftslogik. Um die Systemleistung und das Benutzererlebnis zu verbessern, erwägen Entwickler häufig die Verwendung asynchroner Aufgaben, um einige zeitaufwändige Vorgänge auszuführen, z. B. das Senden von E-Mails, das Verarbeiten von Datei-Uploads, das Erstellen von Berichten usw. Im Bereich PHP bietet das ThinkPHP-Framework als beliebtes Entwicklungsframework einige praktische Möglichkeiten zur Implementierung asynchroner Aufgaben.

So installieren Sie thinkphp So installieren Sie thinkphp Apr 09, 2024 pm 05:42 PM

ThinkPHP-Installationsschritte: Bereiten Sie PHP-, Composer- und MySQL-Umgebungen vor. Erstellen Sie Projekte mit Composer. Installieren Sie das ThinkPHP-Framework und die Abhängigkeiten. Datenbankverbindung konfigurieren. Anwendungscode generieren. Starten Sie die Anwendung und besuchen Sie http://localhost:8000.

Wie ist die Leistung von thinkphp? Wie ist die Leistung von thinkphp? Apr 09, 2024 pm 05:24 PM

ThinkPHP ist ein leistungsstarkes PHP-Framework mit Vorteilen wie Caching-Mechanismus, Codeoptimierung, Parallelverarbeitung und Datenbankoptimierung. Offizielle Leistungstests zeigen, dass es mehr als 10.000 Anfragen pro Sekunde verarbeiten kann und in großen Websites und Unternehmenssystemen wie JD.com und Ctrip in praktischen Anwendungen weit verbreitet ist.

Entwicklungsvorschläge: So verwenden Sie das ThinkPHP-Framework für die API-Entwicklung Entwicklungsvorschläge: So verwenden Sie das ThinkPHP-Framework für die API-Entwicklung Nov 22, 2023 pm 05:18 PM

Entwicklungsvorschläge: So verwenden Sie das ThinkPHP-Framework für die API-Entwicklung Mit der kontinuierlichen Entwicklung des Internets ist die Bedeutung von API (Application Programming Interface) immer wichtiger geworden. Die API ist eine Brücke für die Kommunikation zwischen verschiedenen Anwendungen. Sie kann Datenaustausch, Funktionsaufrufe und andere Vorgänge realisieren und bietet Entwicklern eine relativ einfache und schnelle Entwicklungsmethode. Als hervorragendes PHP-Entwicklungsframework ist das ThinkPHP-Framework effizient, skalierbar und einfach zu verwenden.

See all articles