Das Pipeline-Muster ist ein Entwurfsmuster, bei dem ein Verarbeitungsobjekt (das „Passable”) durch eine Reihe von Pipes (Verarbeitungsschritte) geschickt wird. Jede Pipe erhält die Ausgabe der vorherigen Stufe, wendet ihre Verarbeitung an und reicht das Ergebnis an die nächste weiter.In Laravel implementiert die Klasse Illuminate\Pipeline\Pipeline dieses Muster — die Middleware-Verarbeitung funktioniert exakt nach diesem Prinzip.
Die Pipeline wird im Kern von Laravel breit eingesetzt.
HTTP-Middleware — Illuminate\Foundation\Http\Kernel schickt Requests durch die Middleware-Pipeline
Console-Commands — Vor- und Nachverarbeitung von Artisan-Befehlen
Router-Middleware — Middleware-Anwendung auf Route-Gruppen
Werfen wir einen Blick darauf, wie der HTTP-Kernel die Pipeline nutzt.
// Aus Illuminate\Foundation\Http\Kernelprotected function sendRequestThroughRouter($request){ return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter());}
Die Methode carry() ist das Herzstück der Pipeline. Mit array_reduce werden die Pipes von rechts nach links gefaltet und zu einer verketteten Closure zusammengebaut.
// Intern in Pipeline::then()protected function carry(){ return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { if (is_callable($pipe)) { return $pipe($passable, $stack); } elseif (! is_object($pipe)) { [$name, $parameters] = $this->parsePipeString($pipe); $pipe = $this->getContainer()->make($name); $parameters = array_merge([$passable, $stack], $parameters); } else { $parameters = [$passable, $stack]; } return $pipe->{$this->method}(...$parameters); }; };}
Durch array_reverse werden die Pipes umgekehrt und an array_reduce übergeben, damit die Aufrufreihenfolge stimmt. Der Closure-Stack wird von innen nach außen aufgebaut, sodass die erste Pipe zuerst ausgeführt wird.
Pipelines werden manchmal auch „Zwiebel-Architektur” genannt. Der Request durchdringt die Schichten von außen (erste Pipe) nach innen; die Response läuft von innen nach außen zurück. Deshalb kann jede Middleware sowohl vor als auch nach $next() Verarbeitung einfügen.