Next Generation Flow

Das ist neu in TYPO3 Flow 2.0
Kommentare

Das PHP-Framework TYPO3 Flow ist schon seit 2011 verfügbar und bereits seit Version 1.0 in größeren Projekten im Produktivbetrieb. Mit Erscheinen der Version 2.0 im Juli hat das Projekt wieder einen großen Schritt nach vorn gemacht.

Flow ist ein Framework zur Entwicklung von komplexen PHP-Applikationen, das neben den üblichen Funktionen wie einem MVC-Stack und Templating vor allem Einflüsse aus anderen Programmiersprachen in die PHP-Welt einbringt.

Denn die Unterstützung für Domain-driven Design, aspektorientiertes Programmieren (AOP) oder Dependency Injection (DI) ist nicht nur der Garant für den Sieg im Buzzword-Bingo: Damit wird es möglich, sich in komplexen Projekten auf den Kern des Problems zu konzentrieren, anstatt auf den Kampf mit der Infrastruktur.

Entstanden ist Flow im Rahmen der Entwicklung des Content-Management-Systems Neos im TYPO3-Projekt. Bereits 2006 wurde begonnen, die nächste Generation des bekannten, webbasierten TYPO3-CMS zu entwickeln, und nach einer langen Alpha-Phase wurde das Framework 2011 unter dem Namen FLOW3 veröffentlicht. Im Oktober 2012 wurde im Zuge eines Rebranding der Name in TYPO3 Flow geändert.

Neuerungen in Flow 2.0

Die Arbeiten an Flow 2.0 begannen noch unter dem Namen FLOW3 und sollten als Version 1.2 veröffentlicht werden. Nach dem Rebranding und dem damit veränderten Namen – der sich auch in den im PHP-Code verwendeten Namespaces auswirkte – war das jedoch nicht mehr tragbar, da wir mit dem Projekt den Regeln des Semantic Versioning folgen. Aber auch ohne die Umbenennung enthält die neue Version so viele Verbesserungen und neue Features, dass ein Release als 2.0 die einzige Option darstellte.

Lazy Dependency Injection

Die Nutzung von Dependency Injection in Flow ist im Normalfall um einiges leichter als in anderen Frameworks, da Flow hier, soweit möglich, die nötigen Informationen aus dem Code herausliest. So ist Property Injection in wenigen Zeilen möglich:

/**
* @FlowInject
* @var RobertLemkeExampleBookshopDomainModelBasket
*/
protected $basket;

Der einzige Nachteil an diesem Feature ist seine Einfachheit: Schnell fordert man zahlreiche Abhängigkeiten an, von denen in den meisten Fällen, etwa in einem Controller, der einen Request bearbeitet, nur wenige tatsächlich notwendig sind. Werden jedoch alle Abhängigkeiten instanziiert, um sie zur Verfügung stellen zu können, treibt das Laufzeit und Speicherbedarf in die Höhe, da unter Umständen in der Folge hunderte von Klassen geladen werden. Flow 2.0 begegnet diesem Problem mit Lazy Dependency Injection: Eine Abhängigkeit wird als Proxy zur Verfügung gestellt und erst dann aktiviert, wenn sie tatsächlich benötigt wird. In einem Kundenprojekt hat dies die Zahl der geladenen Klassen auf ein fünfzehntel reduziert. Und ebenso wie DI und AOP in Flow auch dann funktionieren, wenn man eine Klasse mit new instanziiert, ist auch die Lazy DI so weit wie möglich unsichtbar. Lediglich in einigen seltenen Fällen muss man den Proxy explizit aktivieren – hierzu reicht jedoch ein einfacher Methodenaufruf.

if ($this->bookRepository instanceof DependencyProxy) {
  $this->bookRepository->_activateDependency();
}

Mehr Speed durch höhere Geschwindigkeit

Die Geschwindigkeit eines Frameworks kann man unter verschiedenen Aspekten betrachten. Einer davon ist die mögliche Entwicklungsgeschwindigkeit. Hier hat Flow bereits seit Version 1.0 einige handfeste Vorteile gegenüber anderen Frameworks; vor allem dank des Konzepts von Konvention über Konfiguration und die Art, wie das Framework im Hintergrund die „Drecksarbeit“ verrichtet. Der Vergleich mit anderen, teils leichtgewichtigeren Frameworks ließ Flow in Sachen Ausführungsgeschwindigkeit oft (scheinbar) schlecht dastehen. Mit 2.0 wird jedoch erneut klar, dass der Ansatz „Speed ist ein Feature“ praktikabel ist. Durch zahlreiche kleine und größere Änderungen in verschiedenen Teilen des Frameworks konnte ein massiver Zuwachs an Geschwindigkeit erreicht werden. Das zeigt sich bereits in sehr einfachen Beispielen, wie etwa dem Welcome-Paket aus der Flow-Distribution: die Rendering-Zeit dieser nicht gecachten Seite auf Basis eines ebenfalls nicht gecachten Fluid-Templates konnte um den Faktor 20 (zwanzig!) gesteigert werden – was nur noch 25 ms auf dem Laptop des Autors entspricht (Abb. 1). Hinzu kommt der deutlich gesunkene Speicherbedarf, was gerade in komplexen Anwendungen eine nicht unerhebliche Entlastung der Server bedeutet.

Abb. 1: In 25 ms ist die Seite geladen

Abb. 1: In 25 ms ist die Seite geladen

Paketmanagement

Das Dependency-Management-Tool Composer hat sich schnell als De-facto-Standard in der PHP-Welt etabliert. Gemeinsam mit dem PSR-0-Standard für das automatische Laden von Klassen und dem Paket-Repository auf packagist.org entstand die Basis für eine Fülle von vielseitig nutzbaren Komponenten, die unkompliziert in eigene Projekte integriert werden können. Auch Flow nutzt seit Version 2.0 Composer zur Verwaltung der Paketabhängigkeiten und ermöglicht die Einbindung der vorhandenen Pakete. Eine direkte Folge dieser Umstellung war, dass wir von uns genutzte Pakete wie Doctrine ORM oder den YAML-Parser aus Symfony nicht mehr selbst in unser eigenes Paketformat verpacken müssen. Da Flow auch solche Bibliotheken als „Bürger erster Klasse“ behandelt, kann sogar AOP für Code genutzt werden, der nicht Flow-spezifisch entwickelt wurde.

HTTP und REST

Die Komponente mit den meisten „unsichtbaren“ Änderungen in Flow 2.0 ist wohl der komplett neu entwickelte HTTP-Support. Die Objekte, in denen Request und Response von Flow für das MVC-Framework gekapselt werden, basieren nun auf einer vollständig zu HTTP/1.1-kompatiblen Implementierung; testgetrieben anhand des entsprechenden RFCs entwickelt. Damit wird es noch einfacher, durch das Senden korrekter Header Caches wie Varnish bestmöglich zu nutzen. Das ebenfalls in der HTTP-Spezifikation „versteckte“ Konzept der safe request methods fand ebenfalls seinen Weg in Flow 2.0. Dahinter steckt die Definition von GET- und HEAD-Requests als „sicher“ – solche Anfragen dürfen auf dem Server keine Daten verändern, sondern sind nur für den Lesezugriff gedacht. Flow trägt dem Rechnung, indem bei Anfragen über GET und HEAD keine Änderungen an Objekten persistiert werden. Damit würde ein normaler Link zu einer delete-Action in einem Controller zwar die entsprechende Aktion noch fehlerfrei aufrufen, jedoch keinen Effekt mehr auf die gespeicherten Daten haben. Da das Framework nun sicher sein kann, dass solche Requests keine Daten verändern können, ist eine Absicherung gegen Cross-site Request Forgery (CSRF) nicht mehr notwendig, und das recht aufwändige Berechnen von CRSF-Protection-Tokens kann entfallen. Gerade Seiten mit zahlreichen Links profitieren hiervon und können schneller ausgeliefert werden. Auch die Entwicklung (und Nutzung) von REST-Services wurde vereinfacht. Die wohl wichtigste Änderung ist die Unterstützung von HTTP-Method-Tunneling. Damit wird es möglich, HTTP-Methoden wie PUT oder DELETE auch dann zu nutzen, wenn sie vom Client nicht nativ unterstützt werden. Dazu reicht es aus, einen speziellen Header im HTTP-Request zu schicken oder in einem POST-Request die gewünschte Operation als Argument mit dem Namen _method zu übergeben.

Session-Handling ohne PHP

Das Session-Handling in Flow bietet mit dem Session-Scope für Objekte eine sehr einfache Möglichkeit, nicht nur simple Datentypen sondern auch Objekte, ja ganze Objektbäume, in der Session zu speichern. Der automatische Start einer Session kann zudem per Annotation einfach an bestimmte Methodenaufrufe gekoppelt werden (Listing 1).

/**
* A Basket
*
* @FlowScope("session")
*/
class Basket {

  /**
   * Adds a book to the basket
   *
   * @param RobertLemkeExampleBookshopDomainModelBook $book The book to add
   * @return void
   * @FlowSession(autoStart=true)
   */
  public function addBook(Book $book) {
    $this->books->add($book);
  }

}

Flow 2.0 geht in Sachen Session aber einen entscheidenden Schritt weiter: Es benutzt nicht mehr die in PHP vorhandenen Sessionfunktionen sondern eine eigene Implementierung. Denn PHP erlaubt zwar die Nutzung eigener Backends zum Speichern von Sessiondaten, aber der Zugriff darauf, insbesondere das Verändern der Daten, ist nicht vorgesehen. Während der Arbeiten an einer Single-Sign-On-Lösung auf Flow-Basis wurde das jedoch notwendig, um zu Managementzwecken auf beliebige Sessions in einem Verbund von Sites zugreifen zu können. Die neue Sessionimplementierung greift auf das vorhandene Caching-Framework in Flow zurück. Somit können Sessiondaten neben dem Dateisystem auch in allen anderen verfügbaren Cache-Backends (APC, Memcache, PDO-kompatiblen Datenbanken und weitere) abgelegt werden. Neben der Möglichkeit, sich die aktuelle Session einfach als Dependency Injection zur Verfügung stellen zu lassen, ist es über den Sessionmanager nun auch möglich, Sessions über den Identifier oder beliebige Tags abzufragen und zu manipulieren. Werden Sessions etwa mit der Kundennummer eingeloggter Benutzer getaggt, kann der Support bei Problemen dem Kunden direkt helfen:

$session = $this->sessionManager->getSession($sessionId);
$session->putData('username', 'robert');
$session->addTag('user12345');

$session = $this->sessionManager->getSessionByTag('user12345');
$username = $session->getData('username');

Ausblick

Neben dem nicht zu übersehenden Geschwindigkeitszuwachs wurde mit Flow 2.0 vor allem an vielen, weniger offensichtlichen Grundlagen gearbeitet. Viele Verbesserungen bestehender Features sind sehr willkommen aber nicht unbedingt bahnbrechend. Für die Zukunft sind jedoch schon jetzt spannende Neuerungen in Arbeit und zum Teil bereits fertig.

TYPO3 Flow und Neos

Flow eignet sich überaus gut für die Entwicklung von komplexen eigenständigen Applikationen. Seine Wurzeln liegen jedoch in der Entwicklung von TYPO3 Neos. Hieraus ergeben sich völlig neue Möglichkeiten der Integration von individuellen Anwendungen und dem Bedarf nach webbasiertem Content-Management. Da Neos ebenfalls auf Flow basiert, ist sämtliches Know-how sofort auf die Entwicklung von Erweiterungen für Neos anwendbar. Mehr noch: Eine Flow-Applikation lässt sich mit minimalem Aufwand in eine mit Neos realisierte Website integrieren.

Cloud Resources

Das Konzept von Ressourcen zur Abstraktion von Medien (Dokumente, Bilder, Videos, …) ist in Flow schon sehr lange fest verankert. Denn nicht erst seit die ersten PaaS-Hoster den Webserver zur Read-only-Zone erklärten, ist klar, dass die Kopplung von Daten an Dateien auf dem Server nicht zukunftsweisend ist. Die Nutzung von Content Delivery Networks und die Ablage von Daten in Diensten wie Rackspace Cloud Files oder Amazon S3 (mindestens) genauso einfach zu machen wie die Arbeit mit dem lokalen Dateisystem, ist eines der Ziele für Flow 2.1. Einen Überblick zum aktuellen Stand gibt es hier.

Asset Management

Heute sind auch statische Assets einer Website wie das verwendete JavaScript oder die Style Sheets sehr komplex geworden. Dass Kompilieren von SASS oder CoffeeScript oder die Optimierung bestehender JavaScript-Quellen oder -Grafiken wird zunehmend mit Tools wie Assetic realisiert. Eine solche Funktionalität die zudem perfekt mit dem Ressourcenkonzept von Flow zusammenspielt, ist daher für Flow ebenfalls in Arbeit.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -