© istockphoto.com/Vextok
Das PSR-7-Middleware-Framework ZendExpressive

Schnell, leicht, expressive


PSR-7? Middleware? Zend\Expressive? Wir haben also einiges vor in diesem Artikel … am Ende jedenfalls werden wir leichtgewichtige Webanwendungen in kürzester Zeit mit dem neuen PSR-7-Middleware-Microframework aufbauen.

Zend\Expressive ist das neue Zugpferd am Zend-Framework-Himmel. Das „PSR-7-Middleware-Microframework“ verspricht den Aufbau von leichtgewichtigen Webanwendungen innerhalb weniger Minuten. Dieser Artikel wagt einen genaueren Blick auf die Möglichkeiten von Zend\Expressive und betrachtet auch den Aufbau von komplexeren Middlewareanwendungen. Zudem wird die Frage erläutert, ob die Tage des MVC-basierten Zend Frameworks nun gezählt sind. Zunächst beschäftigen wir uns aber mit den Grundlagen.

Was bedeutet PSR-7?

Die „PHP Framework Interop Group“ (PHP FIG) [1] hat sich das Ziel gesetzt, Empfehlungen für gemeinsame Standards in der PHP-Welt zu schaffen. Mitglieder der PHP FIG sind unter anderem Vertreter verschiedener PHP-Frameworks wie Aura, CakePHP, Flow, Laravel, Symfony und Zend Framework, von Tools wie Composer, Doctrine oder Phing sowie von Open-Source-Projekten wie Joomla!, Neos, SugarCRM oder Drupal.

Die Standardempfehlungen der PHP FIG werden idealerweise von möglichst vielen Mitgliedern und Nichtmitgliedern unterstützt. Die Implementierung der Standards funktioniert auf freiwilliger Basis, sodass niemand – nicht mal die Mitglieder der PHP FIG – verpflichtet sind, alle Standards in allen Details umzusetzen. Bekannt und bereits weit verbreitet sind die Autoloading-Standards PSR-0 und PSR-4 sowie die Empfehlungen für Code ­Styles, PSR-1 und PSR-2. Weitere Empfehlungen für Standards sind in Vorbereitung.

Eine relativ junge Standardempfehlung ist der PSR- 7-­Standard [2], der im Mai 2015 akzeptiert worden ist. In diesem Dokument werden eine Reihe von Interfaces zur Darstellung von HTTP-Nachrichten, URIs, Server-Requests und Dateiuploads definiert. Vereinfacht gesagt vereinheitlicht PSR-7 den Zugriff auf HTTP-­Nachrichten auf PHP-Ebene. HTTP-Nachrichten (Requests und Responses) bilden das Gerüst der Web­entwicklung (Abb. 1). HTTP-Clients wie Webbrowser oder Tools wie cURL und wget, aber auch die von JavaScript unterstützten XMLHttpRequest generieren HTTP-Requests und versenden diese an den Webserver. Der Webserver wiederum sendet an den Client zurück.

eggert_expressive_1.tif_fmt1.jpgAbb. 1: Grundgerüst der Webentwicklung

HTTP-Requests und -Responses sind seit Langem standardisiert. In der Vergangenheit hat jedoch nahezu jedes PHP-Framework oder CMS eine eigene PHP-Implementierung zur Darstellung von HTTP-Nachrichten verwendet, was die übergreifende Kommunikation zwischen PHP-Frameworks stark erschwert hat. Durch PSR-7 wird dieser Austausch in Zukunft für alle Projekte vereinfacht, die diese Empfehlung unterstützen.

Die Zend-Framework-Komponente Zend\Diactoros [3] implementiert die Interfaces, die vom PSR- 7-Standard definiert werden. Der Begriff „Diactoros“ stammt aus dem Griechischen und ist ein Schimpfname für den griechischen Gott Hermes; im übertragenen Sinne bedeutet er „der Bote“. Diese Komponente stellt Implementierungen aller Interfaces bereit, die im PSR-7-Standard definiert sind. Dies beinhaltet konkrete Implementierungen für Client-Requests und -Responses, für Server-Requests, Streams, URIs und hochgeladene Dateien.

Was ist eine Middleware?

PSR-7 stellt die Basis dar, um Webprojekte als Middle­wareanwendungen umzusetzen. Dabei hängt sich die Middleware quasi zwischen Request und Response (Abb. 2). Sie kann dabei auf die Daten des Requests zugreifen und zudem alle Daten der Response verändern.

eggert_expressive_2.tif_fmt1.jpgAbb. 2: Der Sitz der Middleware

Bei der Implementierung des Middlewarekonzepts kann zwischen drei Varianten unterschieden werden:

  • Bei der Lambda-Variante wird an die Middleware nur das Request-Objekt übergeben, und die Middleware gibt ein Response-Objekt zurück. Ein Beispiel ist in Listing 1 zu sehen.

  • Die Injected-Response-Variante unterscheidet sich darin, dass sowohl Request- als auch Response-Objekt injiziert werden und das Response-Objekt in veränderter Form zurückgegeben wird (Listing 2).

  • Die dritte Variante trägt den Namen Injected Next Middleware. Sie erweitert die vorherige Variante derart, dass auch die nächste auszuführende Variante injiziert werden kann. Ein entsprechendes Interface finden Sie in Listing 3.

Alle Varianten haben ihre jeweiligen Vor- und Nachteile – somit ist je nach Anforderung eine andere Variante zu bevorzugen. Im Zend Framework wird die dritte Variante implementiert, da sie die flexibelsten der drei Varianten ist und das Aneinanderkoppeln von mehreren Middlewarekomponenten ermöglicht.

Die Komponente Zend\Stratigility [4] ermöglicht die Implementierung von Middleware mit dem Zend Framework und kann Zend\Diactoros einsetzen, um eine Middlewareapplikation aufzusetzen. Der Begriff „Strata“ bedeutet Schicht und kommt aus dem Lateinischen und wurde mit dem englischen Begriff „Agility“ kombiniert. Diese Komponente stellt eine Implementierung des Middlewarekonzepts bereit und ermöglicht die Aneinanderreihung mehrerer Middlewareobjekte, die durch einen Request verarbeitet werden können. Sie ist zudem in der Lage, mithilfe von Error Handlern Fehler abzufangen und zu verarbeiten.

Listing 1

<?php interface LambdaMiddlewareInterface { /** * @param RequestInterface $request * @return ResponseInterface */ public function __invoke($request); }

Listing 2

<?php interface InjectedResponseMiddlewareInterface { /** * @param RequestInterface $request * @param ResponseInterface $response * @return ResponseInterface */ public function __invoke($request, $response); }

Listing 3

<?php interface InjectedNextMiddlewareInterface { /** * @param RequestInterface $request * @param ResponseInterface $response * @param callable $next * @return ResponseInterface */ public function __invoke($request, $response, $next = null); }

Zend\Expressive-Einstieg

Zend\Expressive [5] setzt auf Zend\Stratigility und Zend\Diactoros auf und kombiniert Komponenten wie Router, Servicecontainer und Template-Engine für den Aufbau von Middleware-basierten Webanwendungen. Die Komponente wirbt mit dem griffigen Slogan: „Begin developing PSR-7 middleware applications in minutes!“.

Das klingt erst einmal sehr engagiert und setzt voraus, dass Sie als Entwickler mit dieser Komponente und deren Möglichkeiten vertraut sind. Sobald Sie genügend Erfahrungen mit Zend\Expressive gemacht haben, können Sie tatsächlich in kurzer Zeit Ihre Anwendungen implementieren. Zend\Expressive bündelt dabei den Einsatz verschiedener Komponenten für unterschiedliche Aspekte einer Webanwendung:

  • Routing

  • Dependency-Injection-Container

  • Templateverarbeitung

  • Error Handling

In der ausführlichen Dokumentation [6] finden sich nicht nur Schnellstartanleitungen, sondern auch ausführliche Details zu allen Teilbereichen einer Zend\Expressive-Anwendung sowie ein stetig wachsendes Kochbuch mit hilfreichen Rezepten für den sofortigen Einsatz.

Komponentenbasierter Baukasten

Zend\Expressive wurde als komponentenbasierter Baukasten implementiert, der Ihnen die Wahl zwischen verschiedenen Routern, DI-Containern und Template-Renderern bietet.

Für das Routing haben Sie die Wahl zwischen mehreren Alternativen, die von Zend\Expressive unterstützt werden: Aura.Router [7], FastRoute [8] und Zend\Router [9] stehen zur Auswahl. Bei den Dependency-Injection-Containern können Sie zwischen folgenden Alternativen wählen: Aura.DI [10], Pimple [11] und Zend\ServiceManager [12]. Als Template-Renderer haben Sie die Wahl zwischen Plates [13], Twig [14] und Zend\View [15]. Beim Error Handling schließlich ist die Wahl ein wenig eingeschränkter, da mit Whoops [16] nur eine optionale Alternative unterstützt wird.

In Abbildung 3 finden Sie eine zusammenfassende Übersicht zu den unterstützten Komponenten. Anhand dieser Liste von bereits unterstützten Komponenten können Sie leicht erkennen, dass Zend\Expressive sehr offen ist; es ist kein großes Problem, weitere Komponenten für Routing und zur Templateverarbeitung oder andere DI-Container anzubinden, um sie in Ihrer Middle­wareanwendung mit...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang