TYPO3 Templates: Seiten-Layouts mit Fluid umsetzen
Ursprünglich war die Idee für das Seitentemplate in TYPO3 genauso einfach wie leistungsunfähig. Man hat ein HTML-Template und platziert dort Marker unter Verwendung eines String, der mit den Zeichen „###“ anfängt und wieder aufhört. Später ersetzt man den Marker dann im TypoScript beispielsweise mit dort generiertem Inhalt. Einen Schritt weiter geht der so genannte Subpart – dieser besteht lediglich aus zwei Markern und der Regel, dass alles innerhalb der Marker enthaltene inklusive der Marker selbst mit dem Inhalt ersetzt wird.
Die Schwächen dieses Vorgehens sind offensichtlich. Da es sich bei dem System lediglich um eine Textersetzung handelt, muss TypoScript den kompletten Inhalt inklusive der kompletten Darstellungslogik erzeugen. Will man nun an der Darstellung etwas ändern, kommt man nicht umhin, direkt in das TypoScript einzusteigen und dort die Änderungen vorzunehmen. Ebenso kann das Ganze in einer Arie aus Conditions und Extension-Templates ausarten, wenn man beispielsweise bei jedem Template verschiedenste Untertemplates einbinden will – oder man verwendet dafür spezialisierte Extensions. Wie man es aber dreht und wendet – es ist und bleibt suboptimal.
<!-- ###DOCUMENT begin --> <div id =“content“> ###CONTENT### </div> <!-- ###DOCUMENT end -->
Listing 1
page = PAGE page.10 = TEMPLATE page.10 { template = FILE template.file = fileadmin/site/template/tpl_main.html workOnSubpart = DOCUMENT marks { CONTENT < styles.content.get
Listing 2
Die neue TYPO3 Version 4.5 soll diesen Umstand zumindest dahingehend aufheben, als dass es nun möglich ist, die neue und bislang nur für FLOW3 beziehungsweise für Extbase verwendete Templating-Engine Fluid auch für das Seitentemplating zu benutzen. Dies realisiert das neu eingeführte TypoScript-Objekt „FLUIDTEMPLATE“, das im Hintergrund den ebenfalls in TYPO3 4.5 neu eingeführten Fluid-Standaloneview verwendet.
Installation und Konfiguration
Um das neue TypoScript-Objekt verwenden zu können, muss man sicherstellen, dass Fluid (Extension-Key: fluid) und Extbase (Extension-Key: extbase) im System installiert sind. Dies kann man ganz einfach im Extension-Manager überprüfen.
Im nächsten Schritt kopiert man das bisherige Template und verwendet dort statt des Markers die Zeichenkette {content}. Nun kann TypoScript diese ansprechen:
<div id =“content“> {content} </div>
Listing 3
page = PAGE page.10 = FLUIDTEMPLATE page.10 { template = FILE template.file = fileadmin/site/template/tpl_fluid_main.html variables { content < styles.content.get
Listing 4
Bislang erinnert das Handling an das bekannte Vorgehen, aber es hat sich bereits einiges im Hintergrund getan – unter anderem hat das System die Daten anders transportiert. So gibt es nicht etwa die Content-Elemente der Spalte „Normal“ aus, sondern deren Datenbankinhalt – also ohne die zugehörige HTML-Darstellung. Dies liegt schlicht daran, dass normalerweise die TypoScript-Bibliothek „css_styled_content“ für die Darstellung verantwortlich ist – bei Fluid kann der Nutzer aber selbst im View entscheiden, wie dieser dargestellt werden soll – daher kann der Anwender die Darstellung als HTML explizit anstoßen. Um dies zu realisieren, schreibt man folgendes in das Template:
<div id =“content“> <f:format.html>{content}</f:format.html> </div>
Listing 5
Wer sich bereits mit Fluid beschäftigt hat, sieht sofort, dass hier ein sogenannter Fluid-ViewHelper zum Tragen kommt – eine eigene Klasse innerhalb der Fluid-Systemextension, die in diesem Fall für die Formatierung der Ausgabe in HTML zuständig ist.
Zugriff auf die Seiteneigenschaften
Das Array „data“ übergibt alle Seiteneigenschaften (wie UID, Titel, Navigationstitel) automatisch an den Fluid-View. Die Seiteneigenschaften stehen dementsprechend dort zur Verfügung.
Dafür verantwortlich ist letztlich die Anweisung „$view->assign(‚data‘, $this->cObj->data);“ in der Datei „typo3/sysext/cms/tslib/content/class.tslib_content_fluidtemplate.php“.
Man kann jede der Eigenschaften ganz einfach auslesen, indem man die Eigenschaft als „Schlüssel“ für das Array „data“ verwendet und darauf mit der Punktsyntax von Fluid zugreift:
Sie befinden sich auf der Seite mit der UID {data.uid} und dem Titel {data.title} <f:if condition="{data.layout}==1"> <f:then> Layout-Feld steht auf dem Wert "Layout 1" </f:then> <f:else> Layout-Feld steht NICHT auf dem Wert "Layout 1" </f:else> </f:if> Alle Eigenschaften: <f:debug>{data}</f:debug>
Listing 6
Das Beispiel zeigt auch, wie man im Template das Layout-Feld der Seiteneigenschaften mit dem If-ViewHelper abfragen kann, um daraufhin eine andere Ausgabe zu erzeugen. Dies funktioniert natürlich auch mit allen anderen Feldern.
Eine Übersicht über alle verfügbaren Eigenschaften bietet der Fluid Debug-ViewHelper – diesen zeigt das oben stehende Listing ebenfalls am Ende. So kann man einerseits die zur Verfügung stehenden Schlüssel wie auch deren aktuelle Werte nachsehen.
TypoScript everywhere
Ein Nachteil der bisherigen Marker-Methode besteht darin, dass man im Abschnitt, der die Marker befüllt, festlegen muss, welche TypoScript-Ausgabe man im Template verwenden will. Das bisherige Vorgehen beinhaltete die Integration eines Markers in das Template und die Zuweisung des TypoScript-Objekts an den Marker. Dies ist nicht nur sehr unflexibel, sondern auch fehleranfällig.
Alternativ kann man nun ein FLUIDTEMPLATE verwenden. Schließlich gibt es einen CObject-ViewHelper, der beliebige TypoScript-Objekte direkt ohne vorherige Zuweisung flexibel integriert, in dem man lediglich den TypoScript-Pfad angibt, der irgendwo im TypoScript-Setup definiert sein muss.
Das folgende Beispiel zeigt jeweils, wie die TypoScript-Objekte aufgebaut sind und darunter den jeweiligen Code, um darauf im Template zuzugreifen.
lib.test1 = TEXT lib.test1.value = Aus dem TypoScript! lib.test2 = IMAGE lib.test2 { file = GIFBUILDER file { XY = 300,30 backColor = #cc0000 10 = TEXT 10.text.current = 1 10.fontColor = #ffffff 10.offset = 10, 25 } }
Listing 7
<f:cObject typoscriptObjectPath="lib.test1" /> <f:cObject typoscriptObjectPath="lib.test2">Das wird als Bild gerendert</f:cObject>
Listing 8
Über das Attribut „typoscriptObjectPath“ des „cObject“-ViewHelpers kann man so beispielsweise das TypoScript-Objekt „lib.test1“ adressieren und somit direkt an dieser Stelle ausgeben – ohne es vorher explizit zuzuweisen.
Diese Methode funktioniert aber nicht nur vom TypoScript-Setup ins Template, sondern auch umgekehrt. So kann man Werte aus dem Template an eine TypoScript-Bibliothek übergeben und das Ergebnis wiederum im Template anzeigen lassen. So rendert das zweite Beispiel den String innerhalb des ViewHelpers durch das TypoScript-Objekt „lib.test2“ mit dem GIFBUILDER und zeigt wiederum das Bild im Template an.
Entscheidend ist hier, dass die „Eingabe“ innerhalb des ViewHelpers an das TypoScript-Objekt so übergeben wurde, dass man dort mittels der stdWrap-Eigenschaft „current = 1“ darauf zugreifen kann. Das macht man sich zunutze, indem man bei der GIFBUILDER-Eigenschaft „text“ darauf zugreift.
Layout und Partials
Gerade bei umfangreichen Darstellungen stellt man fest, dass die Ausgabe drei wiederkehrende Bestandteile hat:
- Ein Layout, das beispielsweise CI-Elemente oder eine Bereichsnavigation enthält
- Das Template, das die klassische Ausgabe enthält
- Immer wiederkehrende Teile (Partials), die man nur einmal definiert und an vielen Stellen einbinden kann. Sobald ein bestimmter Abschnitt im Template öfter als einmal unverändert auftaucht, kann man diesen in einem Partial auslagern
Im nächsten Schritt legt man im Verzeichnis „fileadmin“ die beiden Verzeichnisse „Layouts“ und „Partials“ an und konfiguriert den jeweiligen Pfad mit Hilfe von TypoScript (siehe nächster Abschnitt):
page.10 = FLUIDTEMPLATE page.10 { layoutRootPath = fileadmin/Layouts/ partialRootPath = fileadmin/Partials/ }.
Listing 9
Nun kann man beides im Template verwenden:
<f:layout name="defaultLayout" /> <f:section name="content"> <h2>It works :-)</h2> <f:render partial="testpartial" /> Weiterer Text... </f:section>
Listing 10
<h1>Das kommt aus dem Layout</h1> <f:render section="content" />
Listing 11

Die Ausgabe, besonders bei umfangreichen Darstellungen, beinhaltet mit dem Layout, dem Template für die Ausgabe und den Partials (einmal definierte und wiederkehrende Teile) drei wiederkehrende Bestandteile.
Beim Aufbau der Layout-Template-Struktur muss man nun etwas um die Ecke denken:
- Das Template selbst wird über die file-Eigenschaft des FUIDTEMPLATE Content-Objekts definiert und aufgerufen.
- Dieses Template-File kann einen Layout-ViewHelper beinhalten (oben in der ersten Zeile). Dieser bestimmt wiederum das Layout-Template-File. An diesen unter dem Attribut „name“ angegebenen Namen wird „.html“ zugefügt (beziehungsweise die entsprechende zuvor mit der TypoScript-Eigenschaft „format“ festgelegte Formatendung) und das File aus dem ebenfalls per TypoScript konfigurierten Verzeichnis.
- Im Layout-Template-File kann man das Layout definieren. An der Stelle, an der man das Template platzieren will, verwendet man den ViewHelper <f:render section=“content“ />. Als Attribut „section“ benutzt man genau den Namen, den man im Haupt-Template über den Section-ViewHelper <f:section name=“content“> verwendet hat. Damit wird dann der Abschnitt (Section) des Templates gerendert.
- Partials kann man beliebig platzieren, indem man den Render-ViewHelper <f:render partial=“testpartial“ /> verwendet. Hier gilt ebenfalls, dass Fluid im jeweiligen konfigurierten Verzeichnis nach dem Partial sucht, das den angegebenen Namen inklusive der Dateiendung, die per Default .html lautet, haben muss.
TypoScript-Optionen
Zusammenfassend finden Sie in nachfolgender Tabelle alle TypoScript-Optionen, die mit dem Content-Objekt FLUIDTEMPLATE möglich sind.
Auf „file“, „layoutRootPath“ und „partialRootPath“ können zudem stdWrap Eigenschaften angewendet werden.
Option | Bemerkung |
file | Pfad zur Templatedatei (string + stdWrap) |
format | Format – Default ist HTML |
extbase. pluginName |
Festlegen des Plugin-Namens |
extbase. controllerExtensionName |
Festlegen des Extension-Namens |
extbase. controllerName |
Festlegen des Controller-Namens |
extbase. controllerActionName |
Festlegen des Action-Namens |
layoutRootPath | Pfad zu den Layout-Dateien (string + stdWrap) |
partialRootPath | Pfad zu den Partial-Dateien (string + stdWrap) |
variables | Array von Content-Objekten, auf die im Template via Schlüssl zugegriffen werden kann |
stdWrap | StdWrap-Eigenschaften auf die gesamte Ausgabe anwenden |
Fazit
Das TypoScript-Content-Objekt ist bereits jetzt extrem leistungsfähig und unterstützt TYPO3-Entwickler in vielerlei Hinsicht optimal. Zudem stehen so Funktionen zur Verfügung, die mit der klassischen Methode schlicht nicht möglich sind. Man denke beispielsweise alleine an die ViewHelper. Darüber hinaus existieren eigene ViewHelper, die mit wenig Aufwand die Möglichkeiten des Templating erheblich erweitern.
Allerdings fallen einem schnell Dinge auf, die nicht beziehungsweise noch nicht realisiert wurden. So ist es durchaus sinnvoll, dass beispielsweise das Auslesen einer Backend-Spalte nicht alle dort vorhandenen Inhaltselemente als einen String zurückliefern sollte, sondern als Array. Dann könnte man darauf auch andere Viewhelper wie „Cylcle“ oder „For“ anwenden, um so jedes Content-Element einzeln anzusprechen.
Ebenfalls möglich wäre dann vielleicht ein Zugriff auf einzelne Eigenschaften eines Content-Elements. Einem Kommentar im Bugtracker zufolge ist dies für Version 4.6 angedacht.
Und selbst wenn man 100 mal drüber liest… einen Fehler habe ich dann doch übersehen ;-)
Im Listing 4 habe ich die falsche TypoScript Eigenschaft „template“ anstelle von „file“ verwendet – richtig muss das Script also heissen:
page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
file = fileadmin/site/template/tpl_fluid_main.html
variables {
content < styles.content.get
Sorry :-)
Viel Spaß mit FLUIDTEMPLATE
Patrick
Vielen Dank für den Artikel und die Berichtigung!
Hallo Patrick,
danke für den Artikel.
Aber hast du schonmal probiert ein Standardmailformular oder gar eine EXTBase extension mit Formularen anzuzeigen?
Bei den anderen Daten werden bei mir auch massiv viele angezeigt.
Kennst du das Verhalten schon?
Grüße
Kay
@Patrick:
zumindest für das erste problem habe ich eine lösung gefunden ;)
Grüße
Kay
Hi Kay,
tatsächlich – hatte ich gar nicht ausprobiert. Mailform wird per HSC dargestellt… muss ich mal genauer untersuchen…
Grüße
Patrick
Ich bekomme zwar eine Ausgabe mit css-styled-content. es stehen aber diverse um das eigentliche Contentelement umher. Bei Bildern wird zudem die HTML Ausgabe partiell als text ausgegeben. Gibt es eine spezielle css-styled-content für fluid-templates?
Hallo,
sind die Fluid-Templates denn nun schon soweit, dass ich sie ruhigen Gewissens für die Umsetzung einer Live-Site (Typo3 4.5.x) nutzen kann ?
Gerade vor dem Hintergrund, dass man fremde Extensions für News und dergleichen Einbaut bin ich mir da nicht so sicher.
Gibt es diesbezüglich schon Erfahrungen ?
Freu mich auf euer Feedback !
Gruß,
Samuell
Ich find es interessant, dass in dem ganzen Artikel nicht einmal der raw-Viewhelper (seit 4.6.0: ) erwähnt wird. Ohne diesen wird es nämlich ziemlich unmöglich z.B. das Logo der Seite dynamisch als Variable zu übergeben (wobei das Logo als IMAGE cObject besteht). Und auch Navigationen etc. dürften hier Bedarf haben. Will ich wirklich, dass meine Navi von -Tags durchsetzt ist, was mit dem html-Viewhelper gegeben wäre?
Für Leute die den Raw-Viewhelper unter 4.5.x vermissen, die müssen sich eine Extension installieren, welche ihn mitliefert (oder schnell selbst eine schrieben^^).
Aber abgesehen davon, finde ich die FLUID_TEMPLATE Geschichte, wirklich sehr nett und ich benutze sie auch bei neuen Projekten :>
Schöne Grüße
~Armin
Hallo Armin,
es geht auch viel einfacher den RAW-Viewhelper zu benutzen. Einfach den Source von 4.6. runterladen und dort einfach den RAW-Viewhelper in die eigene Fluid Installation kopieren. Dann steht dieser bereits zur Verfügung ;)
Dieser findet sich unter dem Pfad: typo3/sysext/fluid/Classes/ViewHelpers/Format
Naja, dann würde ich lieber ne Mini-Extension schreiben die den ViewHelper zur Verfügung stellt. Das so rein zu kopieren empfinde ich als ziemlich unsauber!
Wenn ich versuche mit verschieden Layouts zu arbeiten, bekomme ich einne Fehler:
Code:
Fehlermeldung:
„Duplicate variable declarations!“
wie es aussieht ignoriert er die IF-Anweisung und führt beide „layouts“ aus!!
hat jemand eine Idee das zu lösen?
Danke!
Berti
>
"
Layout-Feld steht NICHT auf dem Wert "Layout 1"
<f:if condition=“{data.layout}==1″>
<f:then>
<f:layout name=“Layout1″ />“
</f:then>
<f:layout name=“defaultLayout“ />
<f:else>
Layout-Feld steht NICHT auf dem Wert „Layout 1“
</f:else>
</f:if>
</code>
jetzt noch mal der richtge Code, sorry:
<f:if condition=“{data.layout}==1″>
<f:then>
<f:layout name=“Layout1″ />“
</f:then>
<f:else>
<f:layout name=“defaultLayout“ />
</f:else>
</f:if>
@Berti und die Anderen:
Ich würde gerne auch mehrere Page-Layouts nutzen, wei man z.B. mit TemplaVoila auch mehrere Seitenlayouts erstellen kann.
Gibt es irgendwo ein Tutorila oder genauere Details über die Variante von mehreren Layouts mit Fluid?
Ich finde dieses super, jedoch konnte ich bei TemplaVoila auch Bilder mit fixer Höhe und Breite definieren, damit dort nur ein Bild eingefügt werden kann, kann mir da jemand helfen, bis jetzt habe ich nur herausgefunden wie ich weiterhin ein Ressourcenbild einfügen kann oder ein freie Inhaltselemente, jedoch möchte ich dass man nur ein Bild, einen Titel und einen Link bei diesem definierten Bereich einfügen kann.
Kann man das immer noch und wenn ja, wie?
LG