Erste Schritte mit FLOW3 (Update)

Letzten Monat veröffentlichte das Entwicklungsteam von TYPO3 5 die erste Beta-Version des neuen PHP-Frameworks FLOW3; ein bedeutender Meilenstein auf dem Weg zu TYPO3-Version 5. Vor einer knappen Woche folgte dann die zweite Beta. Grund genug, sich einige der Kernfunktionen des noch relativ jungen Frameworks einmal näher anzuschauen. Da aller Anfang ja bekanntlich schwer ist, soll dieser Blog-Artikel zunächst einmal darlegen, wie Ihr überhaupt eigene Pakete in FLOW3 erstellen könnt, und wie eigene FLOW3-Applikationen mit eigenen Funktionen ausgestattet werden können. Update: Seit letztem Donnerstag ist das erste stabile Release des Frameworks erhältlich. Da sich insbesondere bei der Handhabung der Annotations noch einmal einiges geändert hat, gibt es nun noch einmal eine aktualisierte Version des Artikels.

  1. Objektorientierte Programmierung, Domain-Driven Design & MVC-Konzept
  2. Installation und Konfiguration von FLOW3
  3. Anforderungen an die Beispiel-Anwendung
  4. Ein neues Paket „kickstarten“
  5. Die Anwendung mit Leben füllen
  6. Ausblick

Objektorientierte Programmierung, Domain-Driven Design & MVC-Konzept

Die der Entwicklung mit FLOW3 zugrunde liegenden Konzepte ausführlich zu erläutern, würde an dieser Stelle leider den Rahmen sprengen. Grundsätzlich gilt, dass wer sich bereits mit der Extension-Entwicklung mit Extbase beschäftigt hat, sich auch unter FLOW3 ohne Probleme zurecht finden wird – schließlich handelt es sich bei Extbase um die Rückportierung von FLOW3 nach TYPO3 v4. Zum Einstieg ins Domain-Driven Design und das MVC-Konzept finden sich glücklicherweise diverse Hilfestellungen im Netz.

Installation und Konfiguration von FLOW3

Die Installation von FLOW3 ist glücklicherweise keine Raketenwissenschaft, und geht vergleichsweise einfach von der Hand. Die jeweils aktuelle Version von FLOW3 kann über Sourceforge bezogen werden. Die Systemvoraussetzungen beschränken sich auf einen Webserver, PHP in Version 5.3 und eine funktionsfähige Datenbank. Natürlich gibt es die Installation auch ganz vollautomatisch bei Mittwald. Als Kunde könnt Ihr die Software ganze einfach über den Softwaremanager installieren. Wenn Ihr (noch ;-)) nicht bei Mittwald seid, könnt Ihr Euch einen kostenlosen Testaccount mit vorinstalliertem FLOW3 bestellen.

Nach dem Entpacken der ZIP-Datei findet Ihr zunächst die Verzeichnisse Configuration, Data, Packages und Web, sowie eine ausführbare Datei namens „flow3“. Das „Configuration“-Verzeichnis enthält dabei die Konfigurationsdateien (wer hätte das gedacht? ;-)); das „Data“-Verzeichnis beinhaltet verschiedene flüchtige und nicht-flüchtige Daten (die Euch zunächst nicht interessieren müssen); im „Packages“-Ordner sind sämtliche Programm-Quelltexte gespeichert (sowohl die vom Framework, als auch Eure eigenen Quelltexte). Das „Web“-Verzeichnis ist der eigentliche Document-Root der Anwendung. Damit das Framework funktioniert, müsst Ihr den Document-Root des VirtualHost-Eintrags Eures Webservers auf dieses Verzeichnis umbiegen.

Da in diesem Tutorial eine Anwendung programmiert werden soll, die Daten dauerhaft in einer Datenbank speichert, muss nun außerdem noch eine Datenbankverbindung konfiguriert werden. Hierzu findet Ihr im Configuration-Verzeichnis eine Datei „Settings.yaml.example“, die in „Settings.yaml“ umbenannt werden muss. In diese Konfigurationsdatei könnt ihr die Zugangsdaten zur Datenbank eintragen. Die Konfigurationsdatei sollte dann in etwa so aussehen:

Anforderungen an die Beispiel-Anwendung

Das Donämenmodell der Anwendung besteht zunächst aus den beiden Objekten "Konzert" und "Künstler".

Unsere Beispiel-Anwendung soll eine einfache Termin-Verwaltung für einen – natürlich fiktiven – Konzert-Veranstalter implementieren. Die Anwendungen soll Konzerttermine und Künstler verwalten; später sollen Besucher auf der Seite Karten reservieren, und hierzu ihre Kontaktdaten hinterlegen können.

Das Domänen-Modell besteht in diesem Fall also aus den beiden Objekten „Künstler“ und „Konzert“. Die Reservierungen werden wir in einem späteren Beispiel noch einmal genauer betrachten.

Ein neues Paket „kickstarten“

Um ein neues Paket zu erstellen, müsst Ihr euch zunächst einen Paket-Schlüssel überlegen. Dieser dient – ähnlich wie der Extension-Key einer TYPO3-Erweiterung – dazu, dieses Paket eindeutig zu identifizieren. In der Regel besteht ein Package-Key aus dem eigentlichen Paketnamen und einem Vendor name, also einem Kürzel für die Person oder Organisation, die das Paket erstellt hat. Der Name des Vendors und der eigentliche Paketschlüssel werden von einem Punkt getrennt. Beide werden – wie alle Namen in FLOW3 – im „Upper Camel Case“ erwartet. In unserem Fall könnte als Paketname also beispielsweise MW.Concerts verwendet werden.

Erstellen des Pakets

Eine Eingabe von "./flow3 help" zeigt alle verfügbaren Befehle des FLOW3-Kommandozeilen-Clients an.

FLOW3 bringt eine mächtige Kommandozeilen-Schnittstelle mit sich, über die Ihr auf nahezu alle Funktionen des Frameworks zugreifen könnt. Wenn Ihr auf der Konsole in Euer FLOW3-Verzeichnis wechselt, und dort ./flow3 help eingebt, erhaltet Ihr eine Liste aller verfügbaren Kommandos (siehe hierzu auch die Abbildung 2).

Wie Ihr erkennen könnt, ist bereits ein Paket mit dem Namen TYPO3.KICKSTART installiert, welches unter anderem den Befehl kickstart:package anbietet. Dieses Paket kann dazu verwendet werden, eigene FLOW3-Pakete zu erstellen. Mit folgendem Befehl könnt Ihr also das Paket für die Konzert-Verwaltung erstellen:

Wie Ihr an der Ausgabe des Befehls erkennen könnt, hat der Kickstarter neben dem neuen Paket auch gleich einen neuen Controller (mit Namen StandardController) und eine dazugehörige Index-View erstellt. Dieser Standard-Controller wird für unsere Beispiel-Anwendung erst einmal ausreichen. Falls Ihr noch zusätzliche Controller anlegen möchtet, geht dies genauso einfach mit dem Befehl ./flow3 kickstart:controller <Paketname> <Controllername>.

Erstellen der Models

Den Kickstarter könnt Ihr ebenfalls zum Erstellen der Model-Klassen verwenden. Mit ./flow3 kickstart:model <Paketname> <Modelname> kann ein neues Model, mit ./flow3 kickstart:repository <Paketname> <Modelname> ein neues Repository für das entsprechende Model erstellt werden. Beim Erstellen eines Models können als zusätzliche Parameter übrigens bereits die gewünschten Attribute und deren Typ angegeben werden. Der Kickstarter erstellt dann automatisch die entsprechenden Klassen-Attribute und die sondierenden/manipulierenden Methoden für diese.

Mit folgenden Befehlen kann also das Datenmodell mit den dazugehörigen Repositories erstellt werden:

Das fertig erstellte Paket findet Ihr im Ordner Packages/Application/MW.Concerts in Eurem FLOW3-Verzeichnis. Die Verzeichnisstruktur eines Paketes entspricht im Wesentlichen der einer Extbase-Erweiterung unter TYPO3 v4. Neu ist lediglich das Meta-Verzeichnis, in welchem Ihr eine XML-Datei findet, in der Ihr weitere Angaben zu Eurem Paket machen könnt (die package.xml entspricht im Grunde der ext_emconf.php einer TYPO3 v4-Erweiterung).

Erstellen der Datenbank-Tabellen

Für die artists-Eigenschaft des Models muss das Mapping konfiguriert werden

Natürlich müssen die Konzerte und Künstler, die in der Anwendung verwaltet werden sollen, auch irgendwo gespeichert werden. Hierzu ist in FLOW3 das ORM-Framework Doctrine 2 integriert, welches in der Lage ist, komplexe Objektstrukturen auf eine relationale Datenbank abzubilden (und natürlich auch umgekehrt). Mit dem Kommando ./flow3 doctrine:migrate könnt Ihr das Schema Eurer Datenbank an die jeweils installierte FLOW3-Version anpassen (vorausgesetzt, in der Settings.yaml sind die richtigen Verbindungsdaten angegeben). Falls die Datenbank noch leer ist, werden alle benötigten Tabellen angelegt. Genauso kann mit dem Befehl ./flow3 doctrine:update ein bereits bestehendes Datenbankmodell aktualisiert werden.

Der Befehl ./flow3 doctrine:migrate erstellt zunächst eine ganze Reihe an Tabellen, die für das Berechtigungskonzept von FLOW3 benötigt werden. Diese könnt Ihr zunächst einmal ruhigen Gewissens außer Betracht lassen.

Führt Ihr den Befehl doctrine:update aus, wird FLOW3 sich zunächst in einer Fehlermeldung beschweren, dass das Mapping des Feldes artist nicht korrekt sei. Der Grund hierfür ist einfach: Das Attribut artist der Concert-Klasse ist eine Beziehung zu einer anderen Klasse; standardmäßig weiß Doctrine allerdings nicht, was es mit solch einer Beziehung anfangen soll. Lösen könnt Ihr das Problem, indem Ihr die Datei Classes/Domain/Model/Concert.php in dem neuem Paket bearbeitet und den DocComment des artist-Attributs um die Annotation @ORM\ManyToOne(cascade={„all“}) ergänzt (vgl. Abbildung 3).

Nach dieser Anpassung läuft der Befehl ./flow3 doctrine:update artig durch. Wenn Ihr nun einen Blick in die Datenbank werft, werdet Ihr neben den FLOW3-Standardtabellen nun auch die Tabellen mw_concerts_domain_model_artist und mw_concerts_domain_model_concert finden. In diesen Tabellen wird FLOW3, bzw. Doctrine, später unsere Objekte speichern.

Die Anwendung mit Leben füllen

Die Standard-Action des neuen Controllers macht noch nicht allzu viel her.

Das neue Paket kann nun mit dem Befehl ./flow3 package:activate MW.Concerts aktiviert werden (in der Regel sollte das Paket jedoch bereits aktiv sein). Anschließend kann die index-Action des StandardControllers über die URL aufgerufen werden (falls mod_rewrite nicht aktiviert ist, müsst Ihr stattdessen die URL aufrufen).

Wie Ihr seht, kann man mit der Standard-Ausgabe des neuen Controllers noch keinen Blumentopf gewinnen. Im nächsten Schritt sollten wir nun also zusehen, wie wir die Anwendung mit sinnvollen Funktionen füllen können. Um im Controller auf die Konzerte in der Datenbank zugreifen zu können, wird innerhalb des Controllers zunächst eine Instanz des zuvor erstellten ConcertRepository benötigt. Hier kommt eines der neuen Features von FLOW3 zum Einsatz, die vielfach genannte Dependency Injection. Um diese zu nutzen, definiert Ihr im Controller ein Attribut, für welches im DocComment der Name der zu injizierenden Klasse definiert, sowie eine @FLOW3\Inject-Annotation angegeben wird (Achtung: Bevor ihr Annotations wie @FLOW3\Inject verwenden könnt, müssen die entsprechenden Annotation-Klassen zunächst per use-Statement importiert werden):

Um schnell einige Daten zum Ausprobieren erstellen zu können, bietet es sich nun an, eine Controller-Action zum Erstellen einiger Beispiel-Daten zu erstellen. Diese könnte beispielsweise wie folgt aussehen:

Anschließend kann die neue Aktion über die URL https://seo-sanitaeter.de aufgerufen werden. FLOW3 liefert nun zwar einen 404-Fehler (das liegt daran, dass noch die View für diese Action fehlt), die entsprechenden Datensätze werden jedoch trotzdem angelegt und in der Datenbank gespeichert.

Um nun die Konzerte auch ausgeben zu können, müsst Ihr in der indexAction zunächst die Konzerte aus dem Repository laden, und dem View zuweisen (ab hier unterscheidet sich das Vorgehen nur noch unwesentlich von dem in Extbase):

Im index-View (standardmäßig gespeichert in Resources/Private/Templates/Standard/Index.html) könnt Ihr nun mit den üblichen Fluid-ViewHelpern die Konzerte ausgeben. Ihr solltet allerdings beachten, dass hier im Gegensatz zu Extbase die gesamte HTML-Seite im Template definiert werden muss (auch wenn diese später in ein Layout ausgelagert werden kann).

Ruft Ihr nun erneut die Index-Action im Browser auf, wird nun eine Liste der soeben erstellten Beispiel-Konzerte dargestellt. Selbstverständlich kann dieses zugegebenermaßen eher rudimentäre Paket mit den üblichen Fluid-Optionen, wie beispielsweise einem komplexeren Layout, verschönert werden. Genau wie in Extbase können dem Controller weitere Methoden für Detail-Ansichten oder zum Anlegen oder Bearbeiten von Konzerten zugewiesen werden.

Ausblick

Selbstverständlich kratzt dieser Blog-Beitrag nur an der Oberfläche der Möglichkeiten, die FLOW3 Entwicklern zur Verfügung stellt. Speziell das AOP-Framework ist eines der großen Alleinstellungsmerkmale von FLOW3, welchem mit Sicherheit noch mehr Aufmerksamkeit gewidmet werden könnte. Auch das von FLOW3 mitgelieferte Security-Framework sollte erwähnt werden; mit Hilfe dieser beiden Komponenten könnte in der Konzert-Verwaltung beispielsweise ein differenziertes Berechtigungskonzept implementiert werden, durch welches bestimmten Administratoren das Bearbeiten von Konzerten und Künstlern erlaubt wird.

Das in diesem Blog-Artikel erstellte Paket kann übrigens natürlich auch heruntergeladen werden. Viel Spaß damit! :)

Kommentare

  1. Gravatar
    Jens am

    Hallo, ich arbeite mich gerade durch das Tutorial, um mich mit TYPO3 Neos vertraut zu machen.
    Leider schaffe ich es nicht, wie im Tutorial beschrieben, den StandardController aufzurufen.

    Jedes Mal bekomme ich im FE die Meldung, dass die Seite nicht gefunden werden konnte.

    Weiß jemand Rat?

    Gruß, Jens

    Antworten
  2. Gravatar
    Stephan am

    Beim Aufruf der Methode dummyData bekomm ich eine Exception „.. ‚country‘ cannot be null..“
    Müsste es daher in der function dummyDataAction() statt $artist->getCountry(‚USA‘); nicht besser $artist->setCountry(‚USA‘); heißen?!

    Gruß, Stephan

    Antworten
  3. Gravatar
    Maik am

    @Babyskull
    Vielen Dank…
    ich hatte nach einer „Kunstpause“ den Fehler noch selbst entdeckt und wollte dies eigentlich hier noch posten. Habs nur irgendwie vergessen… :D
    Sonst super Tutorial… Freue mich schon auf die nächsten dieser Art…

    Antworten
  4. Martin Helmich am

    Hallo zusammen,

    da hatte sich doch tatsächlich ein Tippfehler eingeschlichen. Vielen Dank für den Hinweis! :)

    Schönen Gruß,
    Martin

    Antworten
  5. Gravatar
    Babyskull am

    Falls das Problem noch akut ist:
    Zeile 45 ist diese hier:
    $concert->setDate(new DateTime(’2012-06-06′);
    Fehler: Ein ; obwohl etwas anderes erwartet wird.
    Relativ klar wenn ) von setDate fehlt. Es muss also so heißen:
    $concert->setDate(new DateTime(’2012-06-06′));

    Es liegt also am Tuto und nicht an deinen Künsten.

    Antworten
  6. Gravatar
    Maik am

    Hallo…
    ich hänge jetzt schon eine ganze Weile an diesem Tutorial, leider haut es bei mir nicht hin. Immer wenn ich die dummyData action aufrufe bekomme ich diese Fehlermeldung im log:
    PHP Parse error: syntax error, unexpected ‚;‘ in /home/maik/projekte/flow3/Packages/Application/MW.Concerts/Classes/Controller/StandardController.php on line 45
    und auf der Seite wird eine Fehlermeldung wie: #1297263663: The compile run failed. Please check the error output or system log for more information.
    Allerdings ist da nirgends ein syntax fehler. Die dummyAction hab ich so übernommen wie im Tutrial beschrieben.
    public function dummyDataAction() {
    $this->concertRepository->removeAll();

    $artist = new \MW\Concerts\Domain\Model\Artist();
    $artist->setName(‚Slayer‘);
    $artist->setGenre(‚Thrash Metal‘);
    $artist->getCountry(‚USA‘);

    $concert = new \MW\Concerts\Domain\Model\Concert();
    $concert->setArtist($artist);
    $concert->setLocation(‚Espelkamp‘);
    $concert->setDate(new DateTime(‚2012-06-06‘);

    $this->concertRepository->add($concert);
    }

    Das sind meine ersten Gehversuche mit FLOW3. Vielleicht hat ja jemand einen Tipp für mich.

    Danke

    Antworten
  7. Gravatar
    Martin Brüggemann am

    Karsten meinte „doctrine:migrate“. Wenn man nur ne Runde Models modellieren möchte und sich noch nicht sicher ist, wie das alles mit FLOW3 und Doctrine2 funktioniert, empfehle ich den Befehl „./flow3 doctrine:update –unsafe-mode“, der nach jeder Änderung an den eigenen Models das DB-Schema zuverlässig nachzieht (nicht mit Live-Daten, sondern nur zum Testen verwenden!).

    Antworten
  8. Martin Helmich am

    Hi Karsten,

    erstmal vielen Dank für die Anmerkungen :)

    Zum cascade-Attribut: Davon wäre ich eigentlich auch ausgegangen, zumal der Rest des ORMs ja auch ohne besondere Konfiguration auskommt. Ohne das cascade wirft FLOW3 in der beta2 beim Persistieren allerdings eine Fehlermeldung im Sinne von „A new entity was found through the relationship ‚MWConcertsDomainModelConcert#artist‘ that was not configured to cascade persist operations.“

    Wegen Doctrine; stimmt, erst migrate und dann update ist besser; ich nehme die Anregung mal in den Artikel auf. Danke für den Hinweis. :)

    Schöne Grüße,
    Martin

    Antworten
  9. Gravatar
    Karsten Dambekalns am

    Noch etwas: statt doctrine:create sollte immer am Anfang ein doctrine:mitrate stehen. Für eigenen Code dann gern doctrine:update.

    Antworten
  10. Gravatar
    Karsten Dambekalns am

    Das cascade-Attribut muss nicht angegeben werden, FLOW3 setzt hier sinnvolle Standardwerte auf Basis der erkannten „Aggregate boundaries“.

    Antworten

Kommentar hinzufügen