jochen rau / sebastian kurfürst / martin helmich ... · pdf filejochen rau / sebastian...

24
Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 9783955614 D3kjd3Di38lk323nnm

Upload: nguyenkhanh

Post on 05-Feb-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

D3kjd3Di38lk323nnm

Page 2: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

| V

Inhalt

Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IX

1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Den Server einrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Die Entwicklungsumgebung einrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Weitere hilfreiche Extensions und Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Objektorientierte Programmierung mit PHP . . . . . . . . . . . . . . . . . . . . . . . . . . 12Domain-Driven Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27Model-View-Controller in Extbase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38Test-Driven Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

3 Reise durch das Blog-Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53Erste Orientierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54Die Stationen der Reise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56Die Extension aufrufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57Und Action! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59Blogs aus dem Repository abholen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61Ein Ausflug zur Datenbank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62Pfade auf der Data-Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Zurück im Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65Die Ausgabe durch Fluid rendern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66Das Ergebnis an TYPO3 zurückgeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69Alternative Reiseroute: Einen neuen Post anlegen . . . . . . . . . . . . . . . . . . . . . . 69Automatische Speicherung der Domäne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73Hinweise für Umsteiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

Page 3: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

VI | Inhalt

4 Eine erste Extension anlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79Die Beispiel-Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79Kickstarting der Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80Ordnerstruktur und Konfigurationsdateien . . . . . . . . . . . . . . . . . . . . . . . . . . . 84Das Domänenmodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86Produkte haltbar machen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88Den Ablauf steuern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91Das Template anlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92Das Plugin konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94Installation und Einrichtung der Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

5 Die Domäne modellieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99Die Anwendungsdomäne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100Das Domänenmodell implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

6 Die Persistenzschicht einrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123Die Datenbank vorbereiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124Eingabemasken des Backends konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . 134Individuelle Abfragen implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154Fremde Datenquellen nutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163Klassenhierarchien abbilden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

7 Den Ablauf mit Controllern steuern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171Controller und Actions anlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172Frontend-Plugins konfigurieren und einbinden . . . . . . . . . . . . . . . . . . . . . . . . 187Das Verhalten der Extension konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

8 Die Ausgabe mit Fluid gestalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191Basiskonzepte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191Verschiedene Ausgabeformate verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198Wiederkehrende Snippets in Partials auslagern . . . . . . . . . . . . . . . . . . . . . . . . 200Die Darstellung mit Layouts vereinheitlichen . . . . . . . . . . . . . . . . . . . . . . . . . . 201TypoScript zur Ausgabe nutzen: der cObject-ViewHelper . . . . . . . . . . . . . . . . 202Zusätzliche Tag-Attribute mit additionalAttributes einfügen . . . . . . . . . . . . . . 205Boolesche Bedingungen zur Steuerung der Ausgabe verwenden . . . . . . . . . . . 206Einen eigenen ViewHelper entwickeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208PHP-basierte Views einsetzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215Template-Erstellung am Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 4: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Inhalt | VII

9 Mehrsprachigkeit, Validierung und Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . 225Eine Extension lokalisieren und mehrsprachig auslegen . . . . . . . . . . . . . . . . . 225Domänenobjekte validieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235Sichere Extensions programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

10 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255Backend-Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255Extensions erweitern und erweitern lassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257Migration auf TYPO3 Flow und TYPO3 Neos . . . . . . . . . . . . . . . . . . . . . . . . 261

A Coding Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263

B Referenz für Extbase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

C Referenz für Fluid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327

Page 5: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

| 79

First

Max.Linie

Max.Linie

Kapitel 4 KAPITEL 4

Eine erste Extension anlegen

In diesem Kapitel lernen Sie die Grundzüge einer auf Extbase und Fluid basierendenExtension kennen. Sie legen eine minimalistische Extension an, die auf die absolut not-wendigen Strukturen beschränkt ist. Damit bleibt der Blick für das Ganze frei, ohne sichin den Details zu verlieren. In den folgenden Kapiteln wenden wir uns dann einem kom-plexeren Beispiel zu, um alle wesentlichen Merkmale von Extbase und Fluid erschöpfendzu behandeln.

Die Beispiel-ExtensionUnsere erste Extension soll eine Liste eines Lagerbestands an Produkten ausgeben kön-nen, die wir zuvor im Listen-Modul des Backends angelegt haben. Jedes Produkt istdurch einen Titel, eine kurze Beschreibung sowie die Anzahl der am Lager befindlichenStücke gekennzeichnet.

Zur Erstellung der Extension werden wir zunächst den seit August 2011 im TER verfügba-ren Extension Builder nutzen. Im nächsten Schritt werden wir uns die vom Extension Buil-der generierten Dateien genauer anschauen, um den Aufbau einer Extbase-Extension bes-ser verstehen zu können, und diese Dateien gegebenenfalls unseren Bedürfnissen anpassen.

Folgende Schritte sind für die Umsetzung der Extension notwendig. Sie können sie vonHand durchführen (und genau das werden wir in einem weiteren Beispiel ab Kapitel 5der Übung halber auch tun) oder diese Schritte vom Extension Builder erledigen lassen:

1. Ordnerstruktur und die minimal notwendigen Konfigurationsdateien anlegen

2. Problemdomäne in ein abstrahiertes Domänenmodell (Model) übersetzen

3. Konfiguration der Persistenzschicht einrichten

• Definition der Datenbanktabellen anlegen

• Anzeige der Formulare für das Backend konfigurieren

• Repositories für Produktobjekte anlegen

4. Ablauf innerhalb der Extension festlegen (Controller und Action-Methoden anlegen)

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 6: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

80 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

5. Design in HTML-Templates umsetzen

6. Plugin zur Anzeige der Listen konfigurieren

7. Die Extension installieren und testen

Wir haben die Reihenfolge der Schritte innerhalb der Beispiel-Extensions sogewählt, dass die Zusammenhänge sichtbar bleiben und sich ein »natürliches«Wachstum der Extension und Ihres Wissens ergibt. Nachdem Sie die erstenErfahrungen in der Programmierung mit Extbase gesammelt haben, werden Siediese Schritte wahrscheinlich in einer etwas anderen Reihenfolge und schnellerdurchlaufen wollen. Wir weisen an den entsprechenden Stellen darauf hin.

Kickstarting der ExtensionZunächst installieren wir nun den Extension Builder und nehmen dann die Grundkonfi-guration der Extension vor.

Installation des Extension BuilderUm den Extension Builder nutzen zu können, müssen Sie diesen zunächst aus demTYPO3 Extension Repository installieren. Wechseln Sie hierzu in den Extension Managerim TYPO3-Backend, und wählen Sie im oberen Auswahlmenü die Option Get Exten-sions. Suchen Sie im Eingabefeld nach dem Extension-Key extension_builder, und instal-lieren Sie die Extension per Klick auf das Symbol mit dem roten Pfeil (Abbildung 4-1).

Abbildung 4-1: Installation des Extension Builder über den Extension Manager

Page 7: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Kickstarting der Extension | 81

Rechts

Max.Linie

Max.Linie

Im Backend-Menü finden Sie nun im Bereich Admin Tools den Punkt Extension Builder.Wählen Sie diesen Punkt das erste Mal aus, präsentiert die Extension eine Kurzeinfüh-rung in ihre Benutzung. Diese können Sie ruhig überspringen (Sie haben ja dieses Buch)und gleich im oberen Auswahlmenü die Option Domain Modelling auswählen.

Grundkonfiguration der ExtensionDie Oberfläche des Extension Builder ist in zwei Bereiche aufgeteilt: Der rechte Bereichdient der Domänenmodellierung (dazu mehr im nächsten Abschnitt); im linken Bereichhingegen können Sie die Grundkonfiguration Ihrer Extension vornehmen.

Hier finden wir zunächst Eingabefelder für den Extension-Namen, den Vendor Nameund den eindeutigen Bezeichner unserer Extension (Extension-Key). Den Extension-Keysetzen wir auf inventory, und damit legen wir zugleich den Namen der Extension aufInventory fest. Der Vendor Name, der vom Extension Builder verlangt wird, wird späterals herstellerabhängiger erster Teil der PHP-Namensräume der erstellten Klassen verwen-det. Vendor Namespaces können prinzipiell frei gewählt werden und müssen im Unter-schied zu Extension-Keys auch nicht registriert werden. Wenn Sie eine Extension im TERveröffentlichen wollen, sollten Sie zuvor also mit einer kurzen Suche (beispielsweise aufgit.typo3.org und github.com) sicherstellen, dass dieser Vendor Namespace nicht bereitsgenutzt wird.

In unserem Beispiel wählen wir als Vendor Namespace OReilly.

Der Name einer Extension wird immer in UpperCamelCase (beginnend miteinem Großbuchstaben, dann Groß- und Kleinbuchstaben, kein Unterstrich)geschrieben, während der Extension-Key nur Kleinbuchstaben und Unterstri-che enthalten darf (lower_underscore). Eine Übersicht über die Namenskon-ventionen finden Sie in Anhang A, Coding Guidelines.

Unter dem Punkt More options finden Sie weitere Konfigurationsmöglichkeiten für IhreExtension. Hier können Sie beispielsweise festlegen, in welcher Kategorie Ihre Extensionim Extension Manager dargestellt werden soll (die Standardeinstellung Frontend pluginsist bereits sinnvoll) oder welche Versionsnummer Ihre Extension tragen soll (für denAnfang bietet sich 1.0.0 an). Ebenso können Sie konfigurieren, von welcher TYPO3-Ver-sion Ihre Extension abhängig sein soll. Je nach Ihrer Auswahl füllt der Extension Builderdas Feld Depends On automatisch mit den passenden Extbase- und Fluid-Versionen(siehe Abbildung 4-2).

Nachdem Sie alle nötigen Einstellungen vorgenommen haben, können Sie Ihre Extensionmit einem Klick auf Save zwischenspeichern. Übrigens können Sie Ihre Arbeit mit demExtension Builder zu jedem Zeitpunkt unterbrechen und die Bearbeitung der Extensionüber die Schaltfläche Load später wieder aufnehmen.

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 8: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

82 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

Erstellung des DomänenmodellsDie Domäne unserer ersten Extension ist sehr schlicht. Der wesentliche Begriff dieserDomäne ist das »Produkt«. Alle für uns wichtigen Eigenschaften eines Produkts und des-sen »Verhalten« werden in einer Klasse mit dem Namen Product definiert (die nötigenNamensräume werden dann vom Extension Builder angelegt).

Um im Extension Builder eine neue Klasse zu definieren, klicken Sie im rechten Bereichauf den mit New Model Object beschrifteten Kasten und ziehen diesen in den freienBereich. Auf der »Zeichenfläche« erscheint nun ein neuer Bereich, in dem Sie die neueKlasse konfigurieren können. Der Klassenname kann zunächst in der Titelzeile bearbeitetwerden (klicken Sie auf click to edit, um den Klassennamen Product eingeben zu können).

Der eigentliche Konfigurationsbereich einer Klasse teilt sich in vier Abschnitte auf: Domainobject settings, Default actions, Properties und Relations. Zunächst können Sie im Abschnitt

Abbildung 4-2: Grundkonfiguration der Beispiel-Extension über den Extension Builder

Page 9: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Kickstarting der Extension | 83

Rechts

Max.Linie

Max.Linie

Domain object settings eine grundlegende Konfiguration vornehmen. Hierzu gehört bei-spielsweise, ob es sich bei der Klasse um eine Entity oder um ein Wertobjekt handeln soll(hier ist der Typ Entity sinnvoll) oder ob es sich um eine Aggregatwurzel handelt. Da unserDomänenmodell nur aus einer Klasse besteht, ist diese logischerweise auch die Aggregat-wurzel (auch wenn das Aggregat hier nur aus einer einzigen Klasse besteht).

Ganz konkret bewirkt das Häkchen bei Is aggregate root hier vor allem, dass der Exten-sion Builder ein Repository für diese Klasse (also ein ProductRepository) und einen ent-sprechenden ActionController (also den ProductController) erstellt.

Im Abschnitt Default actions können Sie definieren, welche Controller-Actions standard-mäßig vom Extension Builder angelegt werden sollen. Da wir zunächst nur Produkte aus-

Abbildung 4-3: Erstellen des Domänenmodells über den Extension Builder

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 10: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

84 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

geben (und nur über das TYPO3-Backend welche anlegen) möchten, reicht hier derHaken bei der list-Action.

Im Abschnitt Properties können Sie schließlich die Attribute der Product-Klasse festlegen.Für dieses einfache Beispiel reicht es zunächst aus, wenn jedes Produkt einen Namen(name), eine Beschreibung (description) und einen Lagerbestand (quantity) hat. Über dieSchaltfläche Add können Sie die entsprechenden Attribute anlegen. Als Attributtypensollten Sie jeweils String, Text und Integer wählen. Außerdem ist es sinnvoll, die Attributename und quantity als required zu markieren.

Nach dem Erstellen der Klasse können Sie die Extension erneut über die SchaltflächeSave speichern.

Erstellen eines Frontend-PluginsUm Ihre Extension später als Inhaltselement im Frontend einfügen zu können, müssen Sienun noch ein Frontend-Plugin definieren. Dies können Sie im linken Bereich des Exten-sion Builder im Abschnitt Frontend plugins über die Schaltfläche Add tun. Den Namen desPlugins können Sie frei vergeben (dieser wird im Backend verwendet, wenn Sie dieses Plug-in als Inhaltselement einfügen möchten). Der Plugin-Key wird später mit dem Extension-Key verkettet und folgt denselben Namenskonventionen (lower_underscore). Ein »traditi-oneller« Plugin-Key wäre beispielsweise pi (abgekürzt für plug-in) oder pi1.

Unter Advanced options können Sie zudem definieren, auf welche Controller-Actionsüber das Plugin zugegriffen werden kann. Da unsere Extension derzeit nur einen Con-troller mit einer Action hat, können Sie sich diese Angabe zunächst sparen.

Ihre Arbeit mit dem Extension Builder ist nun fürs Erste getan. Speichern Sie Ihre Exten-sion ein letztes Mal mit der Save-Schaltfläche. In den folgenden Abschnitten werden wirdie vom Extension Builder generierten Dateien im Detail betrachten.

Ordnerstruktur und KonfigurationsdateienExtensions können in TYPO3 an verschiedenen Orten abgelegt werden. Lokal installierteExtensions sind der Regelfall. Diese befinden sich im Ordner typo3conf/ext/. Global instal-lierte Extensions stehen allen Seiten zur Verfügung, die auf dieselbe Installation zurück-greifen. Sie werden in typo3/ext/ abgelegt. System-Extensions werden mit der TYPO3-Dis-tribution ausgeliefert und befinden sich im Ordner typo3/sysext/. Extbase und Fluid sindBeispiele für System-Extensions. Alle drei Pfade befinden sich unterhalb des Installations-verzeichnisses von TYPO3, in dem auch die Datei index.php liegt.

Der Extension Builder stellt hier keine großen Fragen, sondern legt neue Extensions pau-schal im Verzeichnis typo3conf/ext an. Der Verzeichnisname einer Extension entsprichtimmer dem Extension-Key. Dementsprechend finden Sie die soeben erstellte Extensionalso unter typo3conf/ext/inventory.

Page 11: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Ordnerstruktur und Konfigurationsdateien | 85

Rechts

Max.Linie

Max.Linie

Auf der obersten Ebene liegen die Ordner Classes und Resources. Der Ordner Classes ent-hält alle PHP-Klassen mit Ausnahme von externen Bibliotheken, wie z.B. JavaScript-Bibliotheken. Der Ordner Resources umfasst alle sonstigen Dateien, die noch von unsererExtension verarbeitet werden müssen (z.B. HTML-Templates) oder direkt an das Front-end ausgeliefert werden (z.B. Icons). Innerhalb des Ordners Classes befinden sich dieOrdner Controller und Domain. Der Ordner Controller enthält in unserem Beispiel nureine Klasse, die den gesamten Prozess der Listenerzeugung später steuern wird. Der Ord-ner Domain enthält wiederum die beiden Ordner Model und Repository. Daraus ergibtsich nun innerhalb des Extension-Ordners inventory/ die Ordnerstruktur, die Sie inAbbildung 4-4 sehen.

Damit die Extension von TYPO3 geladen werden kann, werden zwei Konfigurations-dateien benötigt. Diese werden in den Extension-Ordner inventory/ auf der oberstenEbene abgelegt.

Die Datei ext_emconf.php enthält die Metainformationen zur Extension, wie z.B. denTitel, eine Beschreibung, den Status, den Namen des Autors usw. Sie unterscheidet sichnicht von herkömmlichen Extensions. Normalerweise brauchen Sie diese Datei, nach-dem sie vom Extension Builder erstellt wurde, nicht mehr zu bearbeiten.

<?php$EM_CONF[$_EXTKEY] = array( 'title' => 'Inventory List', 'description' => 'An extension to manage a stock.', 'category' => 'plugin', 'author' => 'Jochen Rau', 'author_company' => '', 'author_email' => '', 'state' => 'experimental', 'clearCacheOnLoad' => '1', 'version' => '1.0.0', 'constraints' => array( 'depends' => array(

Abbildung 4-4: Die einfachste Ordnerstruktur mit den grundlegenden Dateien

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 12: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

86 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

'typo3' => '6.0', 'extbase' => '6.0', 'fluid' => '6.0', ) ));

Die Datei ext_icon.gif enthält das Icon der Extension. Hierfür können Sie jede im GIF-Format gespeicherte Grafik verwenden. Sie sollte eine Breite von 18 Pixeln und eine Höhevon 16 Pixeln nicht überschreiten. Das Icon erscheint im Extension Manager und imExtension Repository (TER).

Das DomänenmodellAus der zuvor definierten Klasse Product hat der Extension Builder die Klasse \OReilly\Inventory\Domain\Model\Product erstellt. Der Code dieser Klasse wird in einer Datei mitdem Namen Product.php abgelegt. Der Name der Datei ergibt sich durch das Anhängenvon .php an den eigentlichen Klassennamen (ohne Namensraum). Diese Klassendatei wirdim Ordner EXT:inventory/Classes/Domain/Model/ abgelegt.

Die Bezeichnungen der Klassen müssen in jedem Fall die Ordnerstrukturwiderspiegeln. Extbase erwartet z.B. die Klasse \Vendor\MyExtension\Erster-Ordner\ZweiterOrder\File im Ordner my_extension/Classes/ErsterOrdner/Zwei-terOrdner/File.php. Achten Sie auch auf die entsprechende Großschreibung derOrdnernamen.

Werfen wir nun einen Blick in diese Datei. Beachten Sie, dass die Klasse \OReilly\Inven-tory\Domain\Model\Product von der Extbase-Klasse \TYPO3\CMS\Extbase\DomainObject\AbstractEntity abgeleitet werden muss.

<?phpnamespace OReilly\Inventory\Domain\Model;class Product extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

/** * @var string * @validate NotEmpty **/protected $name = '';

/** * @var string **/protected $description = '';

/** * @var int * @validate NotEmpty

Page 13: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Das Domänenmodell | 87

Rechts

Max.Linie

Max.Linie

**/protected $quantity = 0;

public function __construct($name = '', $description = '', $quantity = 0) {$this->setName($name);$this->setDescription($description);$this->setQuantity($quantity);

}

public function setName($name) {$this->name = (string)$name;

}

public function getName() {return $this->name;

}

public function setDescription($description) {$this->description = (string)$description;

}

public function getDescription() {return $this->description;

}

public function setQuantity($quantity) {$this->quantity = (int)$quantity;

}

public function getQuantity() {return $this->quantity;

}

}?>

Die Eigenschaften (Properties) sind als Klassenvariablen $name, $description und $quan-tity angelegt und durch das Schlüsselwort protected vor direkten Zugriffen von außengeschützt (gekapselt). Die Eigenschaftswerte können nur über die als public deklariertenMethoden setProperty() und getProperty() gesetzt bzw. ausgelesen werden. Methodenin dieser Form werden sehr häufig verwendet und daher kurz Getter und Setter genannt.

Auf den ersten Blick erscheinen Methoden für den Zugriff auf Klassenvaria-blen umständlich zu sein. Sie haben aber mehrere Vorteile: Die Interna derVerarbeitung können zu einem späteren Zeitpunkt hinzugefügt oder geän-dert werden, ohne dass dazu Änderungen am aufrufenden Objekt vorgenom-men werden müssten. Es kann auch z.B. das Auslesen erlaubt werden, ohnedass man gleichzeitig schreibenden Zugriff erlaubt. Die etwas lästige Arbeit,diese Methoden zu schreiben, nimmt Ihnen jedoch der Extension Builder ab.Außerdem bieten die meisten Entwicklungsumgebungen Makros oder Snip-pets für diesen Zweck an.

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 14: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

88 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

Gegenüber der vom Extension Builder erstellten Klasse wurde im obigen Beispiel nochein (nicht unbedingt benötigter) Konstruktor hinzugefügt. Die Methode __construct()dient dazu, einen wohldefinierten Zustand am Anfang des Lebenszyklus des Objektssicherzustellen. Hier werden die Eigenschaften des Produkts gesetzt bzw. mit Wertenvorbelegt.

In der Deklaration des Konstruktors wird das Argument $name mit einem Stan-dardwert (leerer String) vorbelegt und damit optional. Das ist notwendig,damit Extbase die Klasse »leer« instanziieren kann, ohne einen Namen überge-ben zu müssen. Damit verstößt Extbase gegen die reine Lehre, da der Konstruk-tor eigentlich die Minimalkonfiguration des Objekts Organisation sicherstellensoll. Bei Extbase wird dies aber besser über sogenannte Validatoren erledigt(siehe dazu den Abschnitt »Domänenobjekte validieren« in Kapitel 9).

Produkte haltbar machenVon der Klasse \OReilly\Inventory\Domain\Model\Product können wir jetzt bereitsInstanzen – also konkrete Produkte mit individuellen Eigenschaften – zur Laufzeit desSkripts erstellen. Diese sind aber nur in flüchtiger Form im Arbeitsspeicher vorhandenund werden, nachdem die Seite komplett von TYPO3 erzeugt wurde, von PHP wiedergelöscht. Damit die Produkte über eine längere Zeit zur Verfügung stehen, müssen wir sie»haltbar« machen. Üblicherweise geschieht dies, indem man sie in einer Datenbankablegt.

Der Extension Builder hat bereits eine Datei EXT:inventory/ext_tables.sql erstellt, die dienötigen SQL-Befehle zur Erstellung einer Datenbanktabelle für die Product-Objekte ent-hält. Diese sieht (vereinfacht) wie folgt aus:

CREATE TABLE tx_inventory_domain_model_product (uid int(11) unsigned NOT NULL auto_increment,pid int(11) DEFAULT '0' NOT NULL,

name varchar(255) DEFAULT '' NOT NULL,description text NOT NULL,quantity int(11) DEFAULT '0' NOT NULL,

PRIMARY KEY (uid),KEY parent (pid),

);

Dieser SQL-Befehl legt eine neue Tabelle mit den entsprechenden Spalten an. Die Spaltenuid und pid dienen zur internen Verwaltung. Unsere Produkteigenschaften tauchen alsSpalten name, description und quantity wieder auf. Der Extension Builder legt zudemnoch einige weitere Spalten an, die hier der Einfachheit halber ausgelassen wurden. Diesewerden von TYPO3 genutzt, um mehrsprachige Datensätze verwalten und eine Versio-nierung anbieten zu können.

Page 15: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Produkte haltbar machen | 89

Rechts

Max.Linie

Max.Linie

Per Konvention orientiert sich der Name einer Datenbanktabelle stets an derzugehörigen PHP-Klasse. Die Backslashs werden jedoch durch Unterstricheersetzt, und der Tabellenname wird nur im Lowercase geschrieben. Außer-dem wird der Vendor Namespace durch einen generischen tx_ ersetzt.

Auf die Einträge in der Datenbank kann dann über das Backend von TYPO3 zugegriffenwerden. Die Formulare des Backends werden anhand einer Konfiguration erzeugt, die ineinem PHP-Array abgelegt ist, dem sogenannten Table-Configuration-Array (kurz TCA).Innerhalb der Extension wird dann über Repositories transparent auf diese Daten zuge-griffen. »Transparent« bedeutet, dass man sich beim Zugriff auf Repositories um die Artder Speicherung der Daten keine Gedanken machen muss.

Damit das Backend nun weiß, wie es die Produktdaten in einem Formular anzeigen soll,muss das für die Tabelle in den beiden Dateien EXT:inventory/ext_tables.php und EXT:inventory/Configuration/TCA/Product.php konfiguriert werden. Dort wird im Array $TCAunter dem Tabellennamen als Schlüssel die Konfiguration abgelegt. Diese umfasst meh-rere Sektionen. Die Sektion ctrl befindet sich in der Datei ext_tables.php; sie enthältgrundlegende Eigenschaften, wie den Tabellennamen oder die Angabe darüber, welcherTabellenspalte das Label für die Einträge entnommen werden soll.

Die Sektionen columns und types befinden sich in der Datei Configuration/TCA/Product.php. In der Sektion columns wird für jede Tabellenspalte beschrieben, wie diese imBackend angezeigt werden soll. Die Sektion types definiert, in welcher Reihenfolge dieTabellenspalten angezeigt und wie sie gegebenenfalls gruppiert werden.

Die vom Extension Builder generierten Dateien enthalten zusätzlich zu den drei vonIhnen angegebenen Spalten noch diverse weitere Spalten, die von TYPO3 für die Versio-nierung, die Mehrsprachigkeit und zur Steuerung der Sichtbarkeit genutzt werden. Diesewurden im folgenden Codebeispiel der Übersichtlichkeit halber ausgelassen.

Die Möglichkeiten, mit dem TCA die Ausgabe im Backend zu beeinflussen, sindimmens. Im Rahmen diese Buchs können wir diese nur anreißen. Eine voll-ständige Auflistung aller Optionen finden Sie online unter http://docs.typo3.org/typo3cms/TCAReference/.

<?phpif (!defined ('TYPO3_MODE')) die ('Access denied.');

$TCA['tx_inventory_domain_model_product'] = array ('ctrl' => $TCA['tx_inventory_domain_model_product']['ctrl'],'columns' => array(

// 7 TYPO3-interne Spaltendefinitionen ausgelassen'name' => array(

'label' => 'Produktbezeichnung','config' => array(

'type' => 'input',

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 16: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

90 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

'size' => '20','eval' => 'trim,required'

)),'description' => array(

'label' => 'Produktbeschreibung','config' => array(

'type' => 'text','eval' => 'trim'

)),'quantity' => array(

'label' => 'Lagerbestand','config' => array(

'type' => 'input','size' => '4','eval'=> 'int'

)),

),'types' => array(

'1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_ diffsource, hidden;;1, name, description, quantity,--div--;LLL: EXT:cms/locallang_ttc.xlf:tabs.access, starttime, endtime')

),'interface' => array(

'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, description, quantity',

),'palettes' => array('1' => array('showitem' => '')),

);?>

Wir haben in diesem Abschnitt ein Abbild (oder ein Modell) der Realität geschaffen,indem wir nur einen Ausschnitt an Eigenschaften der realen Produkte in Software über-setzt haben, die in unserer Domäne eine Rolle spielen. Dieses von der realen Welt abstra-hierte Modell ist damit vollständig angelegt.

Um auf die im Backend angelegten Objekte zugreifen zu können, wird zudem ein Reposi-tory benötigt. Der Extension Builder hat zu diesem Zweck bereits die Klasse \OReilly\Inventory\Domain\Repository\ProductRepository angelegt, in der die Produkte »abgelegt«sind. Wir können ein Repository auffordern, alle (oder bestimmte) Produkte zu findenund an uns zu übergeben. Die Repository-Klasse ist in unserem Fall sehr kurz:

<?phpnamespace OReilly\Inventory\Domain\Repository;class ProductRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {}?>

Das ProductRepository muss von \TYPO3\CMS\Extbase\Persistence\Repository abgeleitetwerden und erbt von diesem alle Methoden. Es kann daher in unserem einfachen Beispiel

Page 17: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Den Ablauf steuern | 91

Rechts

Max.Linie

Max.Linie

leer bleiben. Die Klassendatei ProductRepository.php legen wir im Ordner EXT:inventory/Classes/Domain/Repository/ ab.

Den Ablauf steuernDer im Backend angelegte Lagerbestand soll nun im Frontend als Liste ausgegebenwerden. Die Erzeugung des HTML-Codes aus den anzuzeigenden Produktobjektenübernimmt der sogenannte View. Extbase verwendet als View standardmäßig dieKlasse \TYPO3\CMS\Fluid\View\TemplateView der Extension Fluid.

Das Bindeglied zwischen dem Model und dem View ist der Controller. Er steuert dieAbläufe innerhalb der Extension und ist in unserem Fall zuständig für die list-Aktion.Diese umfasst das Auffinden der Produkte, die angezeigt werden sollen, sowie die Wei-tergabe dieser ausgewählten Produkte an den zuständigen View.

Der Klassenname des Controllers muss auf Controller enden. Der Extension Builder hatfür uns bereits die Controller-Klasse \OReilly\Inventory\Controller\ProductControllererstellt.

Bei der Namensgebung des Controllers sind Sie im oben beschriebenen Rah-men frei. Wir empfehlen jedoch, einen Controller danach zu benennen, was er»kontrolliert«. Bei größeren Projekten sind dies insbesondere die Aggregate-Root-Objekte (siehe Abschnitt »Aggregates« in Kapitel 2), an denen sich auchder Extension Builder orientiert. Hätten wir den Controller manuell erstellt,hätten wir ihn auch ebenso gut InventoryController nennen können.

In unserem einfachen Beispiel sieht der vom Extension Builder erstellte Controller wiefolgt aus:

<?phpnamespace OReilly\Inventory\Controller;class InventoryController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

/** * @var \OReilly\Inventory\Domain\Repository\ProductRepository * @inject */protected $productRepository;

public function listAction() {$products = $this->productRepository->findAll();$this->view->assign('products', $products);

}

}?>

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 18: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

92 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

Unser \OReilly\Inventory\Controller\InventoryController muss vom \TYPO3\CMS\Ext-base\Mvc\Controller\ActionController abgeleitet werden. Er enthält als einzige Methodedie listAction(). Extbase erkennt alle Methoden, deren Name auf Action endet, als Aktio-nen – also als kleine Ablaufpläne.

Zunächst wird ein geschütztes Klassenattribut namens $productRepository definiert. Die-ses wird von Extbase über den bereits in Kapitel 3 betrachteten Dependency Injection-Mechanismus befüllt. Ausschlaggebend sind hierzu die @inject-Annotation, die dieDependency Injection aktiviert, und die @var-Annotation, die den Typ der angefordertenKlasse beschreibt

Über der listAction() wird das ProductRepository injiziert. Die anzuzeigenden Produkteerhalten wir durch findAll() des Repository. Diese Methode ist in der Klasse \TYPO3\CMS\Extbase\Persistence\Repository implementiert. Welche Methoden Ihnen noch zurVerfügung stehen, können Sie in Kapitel 6 nachschlagen.

Achten Sie darauf, dass Sie zum Erzeugen einer neuen Instanz des Repositoryden Dependency Injection-Mechanismus von Extbase und nicht das Schlüssel-wort new verwenden. Hintergrund für Ortskundige: Das Repository ist einsogenanntes Singleton und ist als solches entsprechend gekennzeichnet.Extbase erkennt das Singleton anhand dieser Kennzeichnung und liefert – nachder erstmaligen Erstellung – immer dasselbe Objekt zurück, unabhängigdavon, an welcher Stelle in Ihrem Code Sie es anfordern. Die Erzeugung mitnew liefert dagegen immer ein neues und damit leeres Repository-Objekt.

Als Ergebnis erhalten wir ein PHP-Array mit den Produktobjekten. Diese geben wirabschließend durch $this->view->assign(...) an den View weiter. Ohne unser weiteresZutun wird am Ende der Aktion der View aufgefordert, den an ihn übergebenen Inhaltauf Basis eines HTML-Templates zu rendern und an TYPO3 zurückzugeben.

return $this->view->render();

Diese Zeile nimmt uns aber Extbase ab, falls wir nicht zuvor selbst den Rendering-Pro-zess anstoßen. Sie kann in unserem Fall also weggelassen werden.

Das Template anlegenIn Extbase werden Templates für das Frontend – falls es nicht anders konfiguriert wird –in einem Unterordner des Ordners EXT:inventory/Resources/Private/Templates/ angelegt.Der Name des Unterordners ergibt sich aus dem letzten Abschnitt des Klassennamensdes Controllers, indem das Suffix Controller weggelassen wird. Aus dem Klassennamen\OReilly\Inventory\Controller\ProductController wird also der Ordnername Product.

Innerhalb des Ordners Product legen wir die Datei mit dem HTML-Template an. DerName der Datei ergibt sich aus dem Namen der aufrufenden Action (im UpperCamel-Case), ergänzt um das Suffix .html. In unserem Fall lautet der Dateiname also List.html.

Page 19: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Das Template anlegen | 93

Rechts

Max.Linie

Max.Linie

Beachten Sie, dass die Datei List.html und nicht ListAction.html heißt. list istder Name der Action. listAction() ist der Name der zugehörigen Methode imController. Ohne weitere Angabe erwartet Extbase die Endung .html. Eskönnen jedoch auch Templates für andere Formate, wie z.B. JSON oder XML,hinterlegt werden. Wie Sie diese ansprechen, können Sie in Kapitel 8,Abschnitt »Verschiedene Ausgabeformate verwenden« nachschlagen.

Das vom Extension Builder erzeugte HTML-Template in der Datei EXT:inventory/Resources/Private/Templates/Product/List.html sieht wie folgt aus:

<f:layout name="Default"/><f:section name="main"><h1>Listing for products</h1>

<f:flashmessages />

<table class="tx_inventory"><tr>

<th><f:translate key="tx_inventory_domain_model_product.name"/></th><th><f:translate key="tx_inventory_domain_model_product.description"/></th><th><f:translate key="tx_inventory_domain_model_product.quantity"/></th><th></th><th></th>

</tr><f:for each="{products}" as="product"><tr>

<td><f:link.action action="show" arguments="{product: product}">{product.name}</f:link.action>

</td><td><f:link.action action="show" arguments="{product: product}">

{product.description}</f:link.action></td><td><f:link.action action="show" arguments="{product: product}">

{product.quantity}</f:link.action></td><td><f:link.action action="edit" arguments="{product: product}">

Edit</f:link.action></td><td><f:link.action action="delete" arguments="{product: product}">

Delete</f:link.action></td>

</tr></f:for>

</table>

<f:link.action action="new">New Product</f:link.action>

Wir geben den Lagerbestand als Tabelle aus. Auf das Array mit den Produktobjekten, diewir im Controller durch $this->view->assign('products', $products) dem View überge-ben haben, können wir nun durch {products} zugreifen. Die mit <f: beginnenden Tagssind Fluid-Tags. Der Code innerhalb des for-Tags wird für jedes Produktobjekt in pro-ducts wiederholt.

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 20: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

94 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

Die layout- und section-Tags dienen der Strukturierung des Inhalts. Eine ausführlicheEinführung in die Verwendung von Fluid-Tags und auch in das Arbeiten mit Layouts fin-den Sie in Kapitel 8, Die Ausgabe mit Fluid gestalten, und in der Referenz in Anhang C.Die translate-Tags dienen der Verwaltung mehrsprachiger Inhalte. Auf diese werden wirin Kapitel 9, Mehrsprachigkeit, Validierung und Sicherheit, noch genauer eingehen.

Sie können das vom Extension Builder erstellte Template nun Ihren eigenen Bedürfnissenanpassen. Vielleicht ist Ihnen aufgefallen, dass innerhalb des Views durch Verwendungdes link.action-Tags auf andere Controller-Actions verlinkt wird, wie beispielsweise aufdie show- und die edit-Action – die es jedoch gar nicht gibt. Darüber hinaus können dieBeschreibungstexte der Produkte unter Umständen sehr lang werden und dabei das Lay-out der Tabelle stören. Hier können Sie das format.crop-Tag verwenden, um den Textauf eine bestimmte Länge zu kürzen.

Insgesamt könnte das angepasste Template also beispielsweise wie folgt aussehen:

<table><tr>

<th>Produkt</th><th>Beschreibung</th><th>Lagerbestand</th>

</tr><f:for each="{products}" as="product">

<tr><td>{product.name}</td><td><f:format.crop maxCharacters="100">{product.description}</f:format></td><td>{product.quantity}</td>

</tr></f:for>

</table>

Bevor wir das Ergebnis im Frontend aufrufen, betrachten wir noch kurz, wie in Extbaseein Frontend-Plugin definiert wird.

Das Plugin konfigurierenEine Extension stellt für die Ausgabe ihrer Daten üblicherweise ein sogenanntes Pluginzur Verfügung. Ein Plugin ist ein Inhaltselement, das wie ein Textelement oder ein Bildauf einer Seite platziert werden kann. Es ist eine »virtuelle« Zusammenstellung von eineroder mehreren Actions. Diese Actions können durchaus in verschiedenen Controllernliegen. In unserem Beispiel gibt es nur eine Controller-Action-Kombination, nämlichProduct->list. Diese Kombination wird in der Datei ext_localconf.php eingetragen, diewir auf der obersten Ebene des Extension-Ordners finden.

<?phpif (!defined ('TYPO3_MODE')) {

die ('Access denied.');}

Page 21: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Das Plugin konfigurieren | 95

Rechts

Max.Linie

Max.Linie

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin('OReilly' . $_EXTKEY,'Pi',array('Product' => 'list')

);

Mit der ersten Zeile wird – wie auch in der Datei ext_tables.php – aus Sicherheitsgründenverhindert, dass der PHP-Code außerhalb von TYPO3 direkt ausgeführt werden kann.Die statische Methode configurePlugin() der Klasse besitzt mehrere Argumente. Mitdem ersten übergeben wir den Vendor Namespace und den Extension-Key, der in derglobalen Variablen $_EXTKEY bereits zur Verfügung steht (ergibt sich aus dem Namen desExtension-Ordners). Mit dem zweiten Argument geben wir dem Plugin einen eindeuti-gen Namen (in UpperCamelCase-Schreibweise). Dieser dient später dazu, das Pluginunter mehreren Plugins auf der Seite eindeutig zu identifizieren. Das dritte Argument istein Array mit allen Controller-Action-Kombinationen, die das Plugin ausführen darf. DerArray-Key ist dabei der Name des Controllers (ohne das Suffix Controller), und dasArray-Value ist eine kommaseparierte Liste aller durch das Plugin ausführbaren Actionsdes Controllers. In unserem Fall ist dies die list-Action (wiederum ohne das SuffixAction). Das Array array('Product' -> 'list') erlaubt also, über das Plugin die MethodelistAction() im \OReilly\Inventory\Controller\ProductController auszuführen.

Standardmäßig wird das Ergebnis aller Actions im Cache abgelegt. Falls das für einzelneActions nicht erwünscht ist, kann man dies mit einem vierten, optionalen Argumentangeben. Es ist ein Array, das analog zum vorherigen aufgebaut ist. Nur werden jetzt alleActions aufgelistet, deren Ergebnis nicht im Cache abgelegt werden soll.

Technisch wird dies dadurch gelöst, dass im automatisch generierten Typo-Script-Code eine Abfrage (Condition) hinzugefügt wird, die je nach BedarfExtbase entweder als Content-Objekt vom Typ USER (gecacht) oder vom TypUSER_INT (ungecacht) aufruft. Sollten Sie also auf der Suche nach Problemenmit dem Caching sein, lohnt ein Blick in dieses generierte TypoScript.

Nun folgt die Registrierung des Plugins, sodass es in der Auswahlbox des InhaltselementsPlugin auftaucht. Dazu dient die folgende Zeile in der Datei ext_tables.php:

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin($_EXTKEY,'Pi','The Inventory List'

);

Der erste Parameter ist wieder der Extension-Key (im Unterschied zur Methode configure-Plugin() allerdings ohne Vendor Namespace!) und der zweite der Name des Plugins. Dasdritte Argument ist ein beliebiger, nicht zu langer Titel des Plugins für die Auswahlbox desInhaltselements.

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 22: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

96 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

Installation und Einrichtung der ExtensionSie können Ihre Extension nun genau so wie aus dem TER heruntergeladene Extensionsüber den Extension Manager installieren.

Nachdem wir die Extension installiert haben, können wir im Backend unsere ersten Pro-dukte anlegen. Wie in Abbildung 4-5 gezeigt, erzeugen wir dazu einen Systemordner, derdie Produkte aufnehmen wird �. Darin legen wir einige wenige neue Bestandsdaten an �.

Anschließend können Sie das Plugin auf einer Seite einfügen (Abbildung 4-6). VergessenSie nicht, den Systemordner, der die Produkte enthält, als Ausgangspunkt (in unseremBeispiel Lager) im Plugin einzutragen. Ihre Produkte werden ansonsten nicht gefunden(siehe Abbildung 4-7).

Abbildung 4-5: Anlegen eines neuen Produkts

Abbildung 4-6: Das Plugin erscheint in der Auswahlbox des Inhaltselements

Page 23: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

Installation und Einrichtung der Extension | 97

Rechts

Max.Linie

Max.Linie

Der nächste Aufruf der Seite, auf der das Plugin liegt, zeigt den Lagerbestand als Tabelle(Abbildung 4-8).

Damit ist die erste kleine Extbase-Extension fertiggestellt. Das Beispiel war bewusst ein-fach gehalten. Es verdeutlicht damit die wichtigsten Arbeitsschritte und einzuhaltendenKonventionen. Zu einer ausgewachsenen Extension fehlen uns aber noch einige Zutaten:

• Reale Domänenmodelle weisen eine hohe Komplexität auf. (Produkte haben z.B.verschiedene Preise und sind Produktkategorien zugeordnet.)

• Mehrere unterschiedliche Ansichten müssen generiert werden (Einzelansicht, Listen-ansicht mit Suche usw.).

Abbildung 4-7: Denken Sie daran, den Systemordner als Ausgangspunkt des Inhaltselements anzugeben

Abbildung 4-8: Die Ausgabe des Lagerbestands im Frontend

Jochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly, ISBN 97839556146909783955614690

Page 24: Jochen Rau / Sebastian Kurfürst / Martin Helmich ... · PDF fileJochen Rau / Sebastian Kurfürst / Martin Helmich, Zukunftssichere TYPO3-Extensions mit Extbase und Fluid, O´Reilly,

98 | Kapitel 4: Eine erste Extension anlegen

Links

Max.Linie

Max.Linie

• Der Webseitenbenutzer soll auf verschiedene Arten mit den Daten interagieren kön-nen (bearbeiten, neu anlegen, sortieren usw.).

• Eingaben des Webseitenbenutzers müssen auf Konsistenz geprüft (validiert) werden.

Die Beispiel-Extension, die wir Ihnen ab Kapitel 5 vorstellen, ist daher wesentlich facet-tenreicher.