FLUIDTEMPLATE

Nach vielen Jahren der Marker- und SubParts ersetzenden Variante mit Hilfe von purem TypoScript bestimmte Teilbereiche einer HTML-Datei zu ersetzen, wurde es Zeit mehr Logik direkt, wie bei Smarty, in das Template selbst auszulagern. TypoScript versteht nicht jeder oder ist für Viele zu komplex. Mit Hilfe der seit TYPO3 4.3 verfügbaren Fluid Engine haben wir ein sehr viel mächtigeres Tool an Bord, das ich Euch nun an Hand von Beispielen erklären will.

templateName

Mit Hilfe von templateRootPaths wird ein Verzeichnis angegeben, in dem sich alle verfügbaren Templates befinden. Damit FLUIDTEMPLATE weiß, welches dieser Templates zu verwenden ist, müsst Ihr mit der Eigenschaft templateName den Dateinamen ohne Dateiextension angeben. Im Template-Verzeichnis gibt es z.B. diese Dateien:

  • Main.html
  • StartPage.html
  • TwoCols.html
  • ThreeCols.html

Mit diesem TypoScript könnt Ihr nun angeben, dass beim Rendern, das Template TwoCols.html verwendet werden soll:

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  # Hier keine Dateiendung angeben!
  templateName = TwoCols
  templateRootPaths {
    10 = EXT:my_sitepackage/Resources/Private/Templates
  }
}

template Bitte mit Vorsicht verwenden

Mit template könnt Ihr das HTML-Template mit Hilfe von TypoScript zusammen bauen. Natürlich macht hier die Zusammenarbeit mit dem ContentObject FILE am meisten Sinn. Jedoch ist das FILE Objekt seit TYPO3 9 deprecated und wird mit TYPO3 10 entfernt. Durch Entfernung dieser Eigenschaft frage ich mich, wie viel Sinn es dann noch macht die template-Eigenschaft überhaupt noch zu verwenden. Denn ein Template komplett mit TypoScript zu erstellen macht IMHO sehr wenig Sinn.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  template = TEXT
  template.value = <h2>{title}</h2>
  variables {
    title = TEXT
    title.data = PAGE:title
  }
}

file

Alternativ zu templateRootPaths, wo Ihr zwischen mehreren Templates wählen könnt, bietet Euch file die Möglichkeit an exakt EIN Template inkl. Pfad anzugeben.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  file = EXT:my_sitepackage/Resources/Private/Templates/MyIndividualLayout.html
}

templateRootPaths

Mit templateRootPaths habt Ihr die Möglichkeit mehrere Verzeichnis-Pfade anzugeben, aus denen das Template, definiert über templateName, geladen werden soll. Jeder Eintrag unterliegt einer Priorität. Je höher die Zahl, desto höher die Priorität.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  # Hier keine Dateiendung angeben!
  templateName = TwoCols
  templateRootPaths {
    0 = news/Resources/Private/Templates
    10 = EXT:my_sitepackage/Resources/Private/Templates
  }
}

Im Beispiel oben haben die Templates aus der news-Extension die niedrigste Priorität. Der 10er Eintrag hat eine höhere Priorität und überschreibt damit die Templates aus der news. Damit bietet sich folgende Möglichkeit: Ihr braucht nicht mehr ALLE Templates aus der news in Eure SitePackage-Extension zu kopieren, sondern nur noch die Datei, die Ihr auch tatsächlich überschreiben wollt. Wenn sich also eine Detail.html in Eurer Extension befindet, so wird diese auch verwendet. Wenn Ihr keine List.html habt, dann fällt Fluid auf die news-Extension zurück und läd die List.html von dort. Dieses Prinzip könnt Ihr mit mehreren solcher Einträge beliebig oft erweitern: 20 = Pfad, 30 = Pfad, 40 = Pfad, ...

layoutRootPaths

Mit layoutRootPaths habt Ihr die Möglichkeit mehrere Verzeichnis-Pfade anzugeben, aus denen die Layouts, definiert über f:layout innerhalb einer Template-Datei, geladen werden soll. Jeder Eintrag unterliegt einer Priorität. Je höher die Zahl, desto höher die Priorität.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  # Hier keine Dateiendung angeben!
  templateName = TwoCols
  templateRootPaths {
    0 = news/Resources/Private/Templates
    10 = EXT:my_sitepackage/Resources/Private/Templates
  }
  layoutRootPaths {
    0 = news/Resources/Private/Layouts
    10 = EXT:my_sitepackage/Resources/Private/Layouts
  }
}

Im Beispiel oben haben die Layouts aus der news-Extension die niedrigste Priorität. Der 10er Eintrag hat eine höhere Priorität und überschreibt damit die Layouts aus der news. Damit bietet sich folgende Möglichkeit: Ihr braucht nicht mehr ALLE Layouts aus der news in Eure SitePackage-Extension zu kopieren, sondern nur noch die Datei, die Ihr auch tatsächlich überschreiben wollt. Wenn sich also eine Detail.html in Eurer Extension befindet, so wird diese auch verwendet. Wenn Ihr keine List.html habt, dann fällt Fluid auf die news-Extension zurück und läd die List.html von dort. Dieses Prinzip könnt Ihr mit mehreren solcher Einträge beliebig oft erweitern: 20 = Pfad, 30 = Pfad, 40 = Pfad, ...

partialRootPaths

Mit partialRootPaths habt Ihr die Möglichkeit mehrere Verzeichnis-Pfade anzugeben, aus denen die Partials, definiert über f:render, geladen werden soll. Jeder Eintrag unterliegt einer Priorität. Je höher die Zahl, desto höher die Priorität.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  # Hier keine Dateiendung angeben!
  templateName = TwoCols
  templateRootPaths {
    0 = news/Resources/Private/Templates
    10 = EXT:my_sitepackage/Resources/Private/Templates
  }
  partialRootPaths {
    0 = news/Resources/Private/Partials
    10 = EXT:my_sitepackage/Resources/Private/Partials
  }
}

Im Beispiel oben haben die Partials aus der news-Extension die niedrigste Priorität. Der 10er Eintrag hat eine höhere Priorität und überschreibt damit die Partials aus der news. Damit bietet sich folgende Möglichkeit: Ihr braucht nicht mehr ALLE Partials aus der news in Eure SitePackage-Extension zu kopieren, sondern nur noch die Datei, die Ihr auch tatsächlich überschreiben wollt. Wenn sich also eine Detail.html in Eurer Extension befindet, so wird diese auch verwendet. Wenn Ihr keine List.html habt, dann fällt Fluid auf die news-Extension zurück und läd die List.html von dort. Dieses Prinzip könnt Ihr mit mehreren solcher Einträge beliebig oft erweitern: 20 = Pfad, 30 = Pfad, 40 = Pfad, ...

format

Hier könnt Ihr angeben welche Dateiendung für die Templates verwendet werden soll. Wenn Ihr Euch die Eigenschaft templateName anschaut, werdet Ihr merken, dass keine Dateiendung anzugeben ist. Und genau das macht Ihr halt mit format. Standard ist html, aber auch xml oder json wären mögliche Dateiendungen.

extbase.pluginName

Wenn Ihr alle extbase.* Eigenschaften angebt, könnt Ihr mit FLUIDTEMPLATE auch Links und Formulare auf Extbase-Plugins weiterleiten.

extbase.controllerExtensionName

Wenn Ihr alle extbase.* Eigenschaften angebt, könnt Ihr mit FLUIDTEMPLATE auch Links und Formulare auf Extbase-Plugins weiterleiten.

Mit dieser Eigenschaft könnt Ihr dem Fluid-Prozess vorgaukeln es würde aus der hier angegebenen Extension heraus aufgerufen werden. Das hat gerade in Bezug auf den f:translate ViewHelper Einfluss, denn mit dieser Angabe hier müsst Ihr nicht mehr den völlständigen Pfad als Key angeben, sondern es reicht, wie bei Extbase gewohnt, nur den reinen Key, ohne Pfad, anzugeben, was die Übersichtlichkeit in den Templates erheblich verbessert.

extbase.controllerName

Wenn Ihr alle extbase.* Eigenschaften angebt, könnt Ihr mit FLUIDTEMPLATE auch Links und Formulare auf Extbase-Plugins weiterleiten.

extbase.controllerActionName

Wenn Ihr alle extbase.* Eigenschaften angebt, könnt Ihr mit FLUIDTEMPLATE auch Links und Formulare auf Extbase-Plugins weiterleiten.

variables

Mit variables könnt Ihr Daten aus ContentObjects an das Fluidtemplate übertragen. Gerade in Bezug auf dynimische Werte ist diese Eigenschaft der settings-Eigenschaft vorzuziehen.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  template = TEXT
  template.value = <h2>{title}</h2>
  variables {
    title = TEXT
    title.data = PAGE:title
  }
} 

settings

Mit settings könnt Ihr statische Daten an das Fluidtemplate übertragen. Gerade in Bezug auf dynimische Werte solltet Ihr lieber auf variables ausweichen.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
  template = TEXT
  template.value = <h2>{title}</h2>
  settings {
    title = Header
    pidOfDetailPage = 1534
  }
} 

dataProcessing

Dokumentation folgt. Im Folgenden mal ein Beispiel, was möglich ist. Ich hole hier alle Unterseiten der Seite mit der UID 1 und lade PRO gefundener Seite alle Dateien, die über die Spalte media verknüpft sind. Dadurch dass der erste DatabaseQueryProcessor jedes einzelne Ergebnis an die data-Eigenschaft des ContentObjectRenderer übergibt, stehen Euch nun im zweiten DatabaseQueryProcessor diese Daten über die TS-Eigenschaft fields und data zur Verfügung. Auf diese Weise lassen sich die DatabaseQueryProcessors schier unendlich in die Tiefe verschachteln und ermöglichen auch komplexe Umsetzungen.

page = PAGE
page.10 = FLUIDTEMPLATE
page.10.file = fileadmin/template.html
page.10 {
  dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
  dataProcessing.10 {
    table = pages
    pidInList = 1
    as = subPages
    orderBy = pages.sorting
    dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
    dataProcessing.10 {
      references.fieldName = media
    }
    dataProcessing.20 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
    dataProcessing.20 {
      table = tt_content
      as = inhalte
      pidInList.field = uid
    }
  }
  dataProcessing.20 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
  dataProcessing.20 {
    #special = directory
    #special.value = 
    levels = 2
    as = mainMenu
    dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
    dataProcessing.10 {
      references.fieldName = media
    }
  }
}

stdWrap

Diese Eigenschaft wird NACH dem Rendering des Fluidtemplates gestartet. Damit habt Ihr die Möglichkeit noch im Nachgang auf das Rendering Ergebnis einzugreifen.