Layout, Template, Partial: wer wen einbindet
Die drei Dateiarten sind in zwei Minuten unterschieden. Die Stunden gehen später drauf, wenn eine Vorlage nicht greift und niemand weiß, aus welchem Pfad sie tatsächlich kommt.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Die eigene Vorlage wird gefunden, benutzt wird trotzdem die alte
Fluid sucht seine Dateien nicht in einem Verzeichnis, sondern in einer nummerierten Liste von Verzeichnissen, und es gewinnt der Treffer mit der höchsten Nummer. Eine Extension liefert ihre Vorlagen unter einem niedrigen Schlüssel, deine eigenen kommen darüber. Wer diese Mechanik nicht kennt, legt seine Datei an einen Pfad, den zwar jemand einmal konfiguriert hat, der aber unter dem der Extension liegt, und wundert sich über die ausbleibende Wirkung.
Der übliche Ausweg macht es schlimmer. Entweder wird das komplette Vorlagenverzeichnis einer Extension kopiert, womit auch alle Dateien mitwandern, die man gar nicht ändern wollte und die künftige Korrekturen nie mehr erhalten. Oder es wird direkt in der fremden Extension editiert, und der nächste Composer-Lauf setzt die Datei zurück, gern unbemerkt kurz vor einem Termin.
Die zweite Baustelle ist Logik, die ins Template wandert. Fluid hat bewusst keinen vollen Zugriff auf PHP: Du kannst keine beliebige Methode mit Argumenten aufrufen, ein Ausdruck wie {objekt.name} funktioniert nur über einen Getter, und Bedingungen können vergleichen, aber nicht rechnen wie eine Programmiersprache. Wer trotzdem alles im Template löst, endet bei verschachtelten Bedingungen, die niemand mehr liest und die kein Test je erfasst.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Ein Aufruf, Bestandteil für Bestandteil
Der Aufruf eines Partials enthält fast alles, was man über Fluid wissen muss: Namensräume, Argumente und die Auflösung über eine Pfadliste.
Der Aufbau
<f:render partial="Teaser/Card" arguments="{item: element}" /> - 01 Der Namensraum
<f:Das Kürzel f steht für den Standardnamensraum, der ohne Anmeldung in jedem Template verfügbar ist. Eigene und fremde ViewHelper bekommen ein anderes Kürzel, das am Dateianfang oder als Attribut am Wurzelelement bekannt gemacht wird. Fehlt diese Zeile, gibt Fluid den Aufruf als Text aus, statt zu meckern.
- 02 Der ViewHelper
renderDerselbe ViewHelper bindet je nach Argument ein Partial oder einen Abschnitt ein. Mit section holt er einen Abschnitt aus der eigenen Datei, und genau darüber greifen Layout und Template ineinander.
- 03 Die Art des Bausteins
partial=Ein Partial ist eine eigene Datei mit eigenem Gültigkeitsbereich, ein Abschnitt bleibt in der Datei, in der er steht, und sieht deren Variablen. Diese Entscheidung ist der eigentliche Unterschied zwischen den beiden.
- 04 Der Name ohne Pfad und ohne Endung
"Teaser/Card"Angegeben wird der Name relativ zum Partial-Verzeichnis, Unterordner mit Schrägstrich, die Dateiendung lässt Fluid weg. Gesucht wird in allen konfigurierten Verzeichnissen, beginnend beim höchsten Nummernschlüssel.
- 05 Die Übergabe
{item: element}Ein Partial sieht ausschließlich, was hier steht. Das ist Absicht und der Grund, warum Partials wiederverwendbar bleiben. Wer stattdessen alle Variablen durchreicht, handelt sich genau die Kopplung ein, die das Partial vermeiden sollte.
Wenn es nicht funktioniert
Das siehst du
Deine Änderung ist im Frontend nicht zu sehen, die bearbeitete Datei ist aber sicher die richtige.
Warum
Aus einem Verzeichnis mit höherem Nummernschlüssel kommt eine gleichnamige Datei und gewinnt.
Was hilft
Im Modul TypoScript unter Aktives TypoScript die Pfadlisten der betroffenen Konfiguration ansehen und den eigenen Schlüssel über den fremden legen.
Das siehst du
Nach dem Eintragen des eigenen Pfads fehlen plötzlich Standardelemente in der Ausgabe.
Warum
Die Pfadliste wurde komplett neu gesetzt statt um einen Schlüssel ergänzt, damit sind die mitgelieferten Verzeichnisse verschwunden.
Was hilft
Nur den eigenen Schlüssel setzen, etwa die 20 neben der vorhandenen 0 und 10, und die bestehenden Nummern unangetastet lassen.
Das siehst du
Auf der Seite stehen sichtbare HTML-Tags mitten im Text.
Warum
Fluid maskiert jede Ausgabe. Das ist der Normalfall und kein Fehler.
Was hilft
Für Inhalte aus dem Rich-Text-Editor den ViewHelper für HTML-Ausgabe verwenden, der den Text zusätzlich durch die konfigurierte Nachbearbeitung schickt. Die rohe Ausgabe nur dort einsetzen, wo der Inhalt nicht aus einer Eingabe stammt.
Das siehst du
Eine Variable ist im Template gefüllt, im Partial aber leer.
Warum
Partials erben nichts. Sie kennen nur die Werte, die im Argumente-Attribut stehen.
Was hilft
An beiden Stellen die vorhandenen Variablen ausgeben lassen und den fehlenden Wert gezielt übergeben, statt pauschal alles durchzureichen.
Das siehst du
Ein eigener ViewHelper erscheint als Text im Quelltext der Seite.
Warum
Der Namensraum ist in dieser Datei nicht bekannt gemacht, deshalb behandelt Fluid den Aufruf als gewöhnliches Markup.
Was hilft
Die Namensraumzeile an den Dateianfang setzen oder das entsprechende Attribut am Wurzelelement ergänzen. In Partials gilt sie nicht automatisch mit.
Fünf Stationen, bis aus einer Fluid-Datei fertiges HTML wird
- 01 TypoScript legt fest, welche Pfadlisten für Layouts, Templates und Partials gelten.
- 02 Fluid nimmt aus jeder Liste den Treffer mit dem höchsten Nummernschlüssel.
- 03 Das Template meldet über den Layout-ViewHelper, welches Gerüst es benutzen will.
- 04 Das Layout ruft die benannten Abschnitte ab und setzt sie an ihre Stelle.
- 05 ViewHelper und Partials füllen den Inhalt, jede Ausgabe wird dabei maskiert.
Was du danach in der Vorlagenschicht sicher entscheidest
Die Templateschicht wird beherrschbar, sobald zwei Fragen jederzeit beantwortbar sind: Woher kommt die Datei, die gerade gerendert wird, und welche Variablen stehen in ihr zur Verfügung. Alles andere folgt daraus.
Zuständigkeiten sauber trennen
Das Layout enthält das umgebende Gerüst und ruft benannte Abschnitte ab. Das Template meldet, welches Layout es benutzt, und definiert diese Abschnitte. Ein Partial ist eine eigene Datei für einen Ausschnitt, der an mehreren Stellen gebraucht wird.
Variablen nachsehen statt vermuten
Ein ViewHelper zum Ausgeben aller vorhandenen Werte beendet die meisten Diskussionen in zehn Sekunden. Besonders lohnend ist der Blick, bevor du eine Bedingung schreibst, denn ein leerer Wert und ein nicht vorhandener Wert sehen im Ergebnis gleich aus.
Tag- und Inline-Schreibweise bewusst wählen
Beide erzeugen dasselbe. Die Tag-Schreibweise ist lesbarer, sobald ein Block Inhalt umschlossen wird, die Inline-Schreibweise gehört in Attribute und in kurze Verkettungen, bei denen ein Wert durch mehrere Formatierungen läuft.
Pfadlisten ergänzen statt ersetzen
Du setzt einen eigenen Schlüssel mit einer höheren Nummer und lässt die vorhandenen Nummern stehen. Damit überlagerst du genau die Dateien, die du selbst mitbringst, und alles andere kommt weiter aus der Extension, inklusive späterer Korrekturen.
Maskierung als Normalfall verstehen
Fluid maskiert jede Ausgabe, deshalb erscheint HTML aus einem Datenfeld als sichtbarer Text. Für Inhalte aus dem Rich-Text-Editor gibt es den passenden Format-ViewHelper, die rohe Ausgabe gehört nur an Stellen, deren Inhalt nicht aus einer Eingabe stammt.
Eigenen ViewHelper schreiben, wenn Logik drängt
Sobald eine Bedingung über zwei Zeilen wächst oder derselbe Kniff im dritten Template auftaucht, gehört er in eine kleine PHP-Klasse. Die ist testbar, hat einen Namen und lässt sich an einer Stelle korrigieren.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Drei Dateiarten, drei Aufgaben
Die Verzeichnisse liegen in einer Extension unter Resources/Private und heißen Layouts, Templates und Partials. Das Layout enthält das umgebende Gerüst, also Kopf, Fuß und Grundraster, und ruft an den passenden Stellen benannte Abschnitte ab. Das Template meldet am Dateianfang, welches Layout es benutzt, und definiert genau diese Abschnitte. Fehlt die Layout-Angabe, wird der gesamte Inhalt der Templatedatei ausgegeben und die Abschnitte werden ignoriert.
Ein Partial ist eine eigene Datei mit eigenem Gültigkeitsbereich. Es kennt keine Variablen der aufrufenden Datei, sondern nur die übergebenen. Ein Abschnitt dagegen bleibt in der Datei, in der er steht, und sieht deren Werte. Daraus folgt die Faustregel: Was an mehreren Stellen gebraucht wird, wird ein Partial, was nur die eigene Datei strukturiert, bleibt ein Abschnitt.
Die Verwechslungsgefahr zwischen beiden ist hoch, weil derselbe ViewHelper sie einbindet. Der Unterschied liegt allein im Argument, und er ist der Grund für die häufigste Überraschung: Nach dem Auslagern eines Abschnitts in ein Partial sind plötzlich die Hälfte der Werte leer.
Woher die Variablen kommen und wie du nachsiehst
Rendert die Seite über das TypoScript-Objekt FLUIDTEMPLATE, kommen die Werte aus drei Quellen: aus den dort gesetzten Variablen, aus den Datenaufbereitungen, die Datensätze einsammeln und als Liste bereitstellen, und aus den Einstellungen, die meist aus den Constants oder aus den Settings eines Site Sets gespeist werden. Der aktuelle Datensatz steht zusätzlich als eigene Variable bereit, bei einer Seite ist das der Seitendatensatz mit allen Feldern.
Bei einer Extbase-Erweiterung ist es einfacher: Dort weist der Controller genau die Werte zu, die im Template ankommen sollen. Wenn etwas fehlt, fehlt es im Controller, und kein Kniff im Template holt es nach.
Statt zu vermuten, lohnt in beiden Fällen die Ausgabe aller vorhandenen Werte über den Debug-ViewHelper. Das Ergebnis beantwortet fast immer beide Fragen auf einmal, nämlich ob der Wert überhaupt existiert und wie er heißt, denn Tippfehler in Variablennamen erzeugen in Fluid keine Fehlermeldung, sondern eine leere Ausgabe.
Die ViewHelper, die du täglich brauchst
Für Bedingungen gibt es f:if mit den Zweigen f:then und f:else, für Wiederholungen f:for, das über eine Liste läuft und über das Argument iteration auf Wunsch mitliefert, ob der aktuelle Durchlauf der erste oder der letzte ist. Für Verweise auf Seiten gibt es f:link.page und, wenn nur die Adresse gebraucht wird, f:uri.page, für die volle Linkauswertung inklusive Dateien und externer Ziele f:link.typolink. Bilder laufen über f:image, das Breite, Höhe und eine Beschnittvariante entgegennimmt und die Datei bei Bedarf erzeugt. Und f:debug gibt aus, was in der Datei tatsächlich ankommt.
Dieselbe Sache lässt sich als Tag oder inline schreiben. Die Tag-Schreibweise ist lesbarer, sobald ein Block umschlossen wird. Die Inline-Schreibweise gehört in Attribute, wo ein Tag gar nicht stehen kann, und in kurze Ketten, bei denen ein Wert nacheinander durch mehrere Formatierungen läuft. Beides mischt sich in derselben Datei problemlos, nur innerhalb einer Zeile wird es schnell unleserlich.
Die vollständige Liste steht in der ViewHelper-Referenz mit allen Argumenten. Sie einmal am Anfang zu überfliegen lohnt sich, weil vieles, was man sonst selbst zusammenbaut, dort schon als fertiger ViewHelper steht, etwa Formatierungen für Datum, Zahlen und Währungen oder das Kürzen von Text auf eine Zeichenzahl.
Wo die Templates gesucht werden
Die drei Pfadlisten für Layouts, Templates und Partials werden im TypoScript als nummerierte Einträge gesetzt. Fluid geht sie von der höchsten Nummer abwärts durch und nimmt den ersten Treffer für den gesuchten Dateinamen. Das bedeutet: Du überlagerst einzelne Dateien, du ersetzt kein Verzeichnis. Eine Datei, die du nicht mitbringst, kommt weiter aus der Extension, samt aller künftigen Korrekturen von dort.
Konfiguriert wird das an mehreren Stellen, und diese Unterscheidung erspart viel Sucherei. Für die Seite selbst stehen die Listen am FLUIDTEMPLATE-Objekt unterhalb von page. Für die Inhaltselemente aus der Systemextension fluid_styled_content hängen sie an deren eigener Konfiguration unter lib. Wer die Vorlage eines Inhaltselements anpassen will und die Pfade der Seite ändert, ändert die falsche Liste.
Für die Ablage der eigenen Dateien gilt dieselbe Regel wie für den Rest der Website. Der richtige Ort ist eine eigene Extension, nicht ein Verzeichnis neben der Installation und schon gar nicht die fremde Extension. Bearbeitete Dateien unterhalb von vendor sind beim nächsten Composer-Lauf weg, ohne dass jemand gefragt wird.
Fluid hat bewusst keinen vollen Zugriff auf PHP
Das ist kein Mangel, sondern eine Entscheidung. Templates werden von Menschen bearbeitet, die kein PHP schreiben, und sie werden aus Dateien geladen, die in vielen Installationen editierbar sind. Deshalb lässt sich in Fluid keine beliebige Methode mit Argumenten aufrufen, ein Punktzugriff funktioniert nur über einen Getter, und die Ausgabe wird standardmäßig maskiert. Was ein Template kann, ist damit von außen absehbar.
Die Grenze verläuft entlang einer einfachen Frage. Was angezeigt wird, entscheidet die Seite, die die Daten liefert, also der Controller oder die Datenaufbereitung im TypoScript. Wie es angezeigt wird, entscheidet das Template. Eine Bedingung, die im Template auswählt, welcher Datensatz überhaupt geholt wird, sitzt auf der falschen Seite dieser Grenze.
Für alles dazwischen gibt es den eigenen ViewHelper: eine PHP-Klasse im Verzeichnis Classes/ViewHelpers der eigenen Extension, mit initializeArguments zum Deklarieren der Argumente und render für die Ausgabe. Danach hat der Kniff einen Namen, eine Datei und eine Stelle, an der er korrigiert wird, und er lässt sich testen, was für eine verschachtelte Bedingung im Template grundsätzlich nicht gilt.
Dazu passende Kurse
Weil die beiden Schichten nur zusammen Sinn ergeben, lohnt es sich, Fluid und TypoScript mit Trainer statt getrennt zu erarbeiten.
Wie sicher bist du beim Thema wirklich?
Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.
Wo du genau das übst
Sehr kompetente und freundliche Trainerin. Die Inhalte wurden gut strukturiert und anhand von anschaulichen Beispielen vermittelt.
Häufige Fragen
Wann nehme ich ein Partial und wann einen Abschnitt?
Warum werden meine HTML-Tags als Text ausgegeben?
Kann ich in Fluid PHP-Funktionen aufrufen?
Muss ich für ein eigenes Design alle Templates kopieren?
Deine Ansprechpartner
Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.
Yves Hoppe
Weiterbildung & Beratung
Hilft dir, aus dem TYPO3-Programm den passenden Kurs für deinen Stand zu finden.
Norbert Jansen
Beratung & Inhouse
Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.
Vorlagen, die ein Update überstehen
Bei cmt arbeitest du die Aufteilung in Layout, Template und Partial an einer laufenden Installation durch und siehst dabei, aus welchem Verzeichnis eine Datei tatsächlich kommt.