Anzeige
Anzeige
UX & Design
Artikel merken

Mehr als nur Old-School-Templating: TypoScript Reloaded

TypoScript kann mehr, als nur Extensions mit der nötigen Konfiguration versorgen. Obgleich es keine klassische Programmiersprache ist, lassen sich doch viele Funktionen erreichen, ohne in PHP programmieren zu müssen. Einfache Datenbankkenntnisse, etwas HTML und ein Verständnis für die Logik von wrap & Co. reichen für erstaunliche Ergebnisse in kurzer Zeit aus.

8 Min. Lesezeit
Anzeige
Anzeige

Zeitreise rückwärts in die Vergangenheit: Heute kann man mit Templavoila (TV) recht einfach das Layout in die Website integrieren. Vorher bestand das Templating in der Nutzung eines reinen TypoScripts. TV schickte sich an, den „alten“ Modern-Template-Building-Ansatz abzulösen.

Anzeige
Anzeige

Aber keine Angst, um unserem Kurs zu folgen, müssen Sie keine antiquarische TYPO3-Version 3.3 installieren. Ganz im Gegenteil, wir werden ausgiebig Gebrauch machen von Erweiterungen und Weiterentwicklungen, die in den Versionen V3.8 bis 4.x Einzug gehalten haben. Syntax und Struktur [1] von TypoScript jedoch setze ich – ebenso wie Grundlagen zu SQL – als bekannt voraus.

TypoScript steht zu Unrecht in dem Ruf, kompliziert zu sein. Wahrscheinlich ist es diesem Vorurteil geschuldet, dass oft unnötigerweise Extensions oder userFuncs für einfachste Funktionen geschrieben werden. Für viele Anwendungen kommt man jedoch mit reinem TypoScript schneller und flexibler zum Ziel.

Anzeige
Anzeige

Als Etappenziel werden wir eine Liste von Frontend-Usern dynamisch erzeugen und, ausgehend von einer einfachen Liste, „Features“ hinzufügen, bis wir schließlich eine Liste erhalten, welche die fünf zuletzt eingeloggten User anzeigt, sortiert nach Zeit und Datum ihres letzten Logins und jeweils verlinkt zu ihrer persönlichen Profilseite. Doch vorab sollten wir uns ins Gedächtnis rufen, wie TYPO3 beim Rendering vorgeht. Unverzichtbares Werkzeug dafür ist der TypoScript-Object-Browser, kurz TSOB (siehe auch „Stressfreie Fehlersuche“).

Anzeige
Anzeige

page.10 ist also ein solches. cObjects sind neben den stdWraps eine der grundlegendsten Funktionen.

Das Objekt darunter ist vom Typ CONTENT, es tritt meist nur sehr unscheinbar in Gestalt von styles.content.get auf, was man mit dem ObjectBrowser (oder durch Studium des CSS Styled Content Templates) leicht herausfinden kann. Aber genau dieses wird uns im weiteren Verlauf genauer interessieren.
So wie es hier verwendet wurde, befragt es die Datenbanktabelle tt_content und holt damit die Inhalte, also Content Elemente (CE) einer Backend-Spalte, auf die Seite. Es spricht jedoch nichts dagegen, den Inhalt aus einer ganz anderen Tabelle zu beziehen. Beispiel:

Anzeige
Anzeige
TypoScript – Setup
lib.userlist = CONTENT
lib.userlist {
 table = fe_users
 // id des Sysordners mit Frontend Usern
 select.pidInList = 51
 renderObj = TEXT
 renderObj {
  // Username
  field = username
  wrap = |<br />
 }
}

Listing 1

Eingebunden wird das mit den folgenden Codezeilen:

TypoScript – Setup
page = PAGE
page {
 10 < lib.userlist
}

Listing 2

Mit nur sechs TypoScript-Anweisungen erhalten wir schon eine unsortierte Liste aller Frontend-User im angegebenen Sysordner. Bevor die Funktionsweise erklärt wird, bohren wir dieses Beispiel noch ein wenig auf:

TypoScript – Setup
lib.userlist = CONTENT
lib.userlist {
 table = fe_users
 select.pidInList = 51
 select.andWhere = lastlogin > ({date:U}-864000)
 select.andWhere.insertData = 1
 select.orderBy = lastlogin DESC
 // nur max 5 User
 select.max = 5
 renderObj = COA
 renderObj {
  10 = IMAGE
  10.file = fileadmin/img/email.gif
  10.altText = write an email
  10.stdWrap.typolink.parameter.field = email
  20 = TEXT
  20.field = username
  30 = TEXT
  // Zeitstempel letzter Login
  30.field = lastlogin
  // formatiere als Zeitdifferenz zum aktuellen Zeitstempel
  30.age = Min|Std|Tage
  30.noTrimWrap = | (|) |
  wrap = <div class=“user-entry“>|</div>
 }
 wrap = <div class=“user-list“><h3>Logins:</h3>|</div>
}

Listing 3

Wie funktioniert das nun? Zuerst wird mit „table“ und „select“ der Datenbank-Query konfiguriert. Wenn man bei der Formulierung von Datenbankabfragen nicht so geübt ist, bietet sich die Suche von phpMyAdmin an, die den ausgeführten Query am Bildschirm ausgibt. Über die select-Attribute lassen sich, neben den hier verwendeten, auch (fast) alle anderen Aspekte eines SQL-Query wie GROUP BY oder Joins definieren. Details und weitere Optionen dazu hält die TSref bereit.

Anzeige
Anzeige

Für jeden Datensatz (hier User) wird dann das renderObj durchlaufen. Es ist selbst vom Typ cObject, kann also jedes Content-Objekt aus der TSref [siehe Kapitel 8] aufnehmen. Das sieht man sehr gut, wenn man Beispiel 1 und 2 vergleicht. Im ersten haben wir direkt ein TEXT verwendet, im zweiten ein COA, womit auch der Aufbau umfangreicherer Konstrukte übersichtlich bleibt. Aus der Praxis lässt sich sagen, dass mit TEXT, COA, IMAGE und CASE bereits 90 Prozent der Anwendungsfälle abdeckbar sind. Aber auch eine Unterabfrage (z. B. um die FE-User-Gruppen jedes Users mitanzuzeigen) lässt sich mit einem weiteren CONTENT im renderObj des fe_users-CONTENT realisieren. Wir werden darauf im nächsten Teil näher eingehen.

Für jeden Durchlauf stellt das CONTENT-Objekt uns einen Datensatz im aktuellen stdWrap-Kontext bereit. Bezogen auf die CE 10, 20 und 30 lässt sich also feststellen, dass dort jeweils alle Felder (Datenbankspalten) eines Abfrageergebnisses zur Verfügung stehen. Wir nutzen das über die stdWrap-Eigenschaften des TEXT-Objekts. Es hält über die Attribute „field“, „data“, „cObject“ und „value/insertData“ gleich mehrere Möglichkeiten bereit.

An dieser Stelle sei noch einmal der Ratschlag gegeben, Links ausschließlich (!) mit Typolink zu erzeugen, statt beispielsweise mit wrap einen mailto-Link per Hand zu erzeugen. Richtig eingesetzt sind Typolinks kurz, klar und funktionieren in jeder TYPO3-Umgebung, d.h. mit/ohne Simulate Static oder auch als Real Url. In unserem Beispiel würde zum Beispiel auch die E-Mail-Adresse automatisch verschlüsselt werden [2]
[3], wenn dies per config.spamProtectEmailAddresses eingestellt ist.

Anzeige
Anzeige

Nun enthält dieses Beispiel noch ein Problem. Wir setzen voraus, dass zu jedem User eine E-Mail-Adresse hinterlegt ist. Wäre in der Datenbank dieses Feld bei einigen Usern leer, so gibt es eine gute und eine schlechte Nachricht. Die gute zuerst: Da wir die TypoLink-Funktion genutzt haben und keinen wrap, wird immerhin der komplette Link weggelassen. Die schlechte: Die Grafik, um die der Link gelegt wird, ist weiterhin sichtbar. Als Lösung erweitern wir das Beispiel erneut:

TYPOSCRIPT – SETUP
renderObj {
	:
	10.if.isTrue.field = email
	:
}

Listing 4

Nun erhalten wir eine Ausgabe, die die Grafik immer dann ausblendet, wenn keine E-Mail hinterlegt ist. Wollen wir diese Grafik stattdessen durch eine andere ersetzen, so fügen wir oben zusätzlich ein:

TYPOSCRIPT – SETUP
renderObj {
	:
	10.stdWrap.override.cObject = IMAGE
	10.stdWrap.override.cObject.file = fileadmin/img/no_email.gif
	10.stdWrap.override.if.isFalse.field = email
  :
}

Listing 5

Anzeige
Anzeige

Die finale Ausgabe sollte dann aussehen, wie die nebenstehende Abbildung. Durch den Einsatz von „if“, „ifEmpty“ und „override“ lässt sich eine Flexibilität erreichen, die bei klassischen Markern in den Templates von Extensions allzu oft schmerzlich vermisst wird.

Früher oder später wird der Punkt kommen, an dem man sehr viele Felder in einem Schwung abrufen möchte. Bisher haben wir die Datenbankfelder mit der Funktion „field“ abgeholt. Doch auch per getText [siehe TSref Kapitel 2.2] stehen sie uns bereit.

Stellen wir uns vor, wir wollen den Usernamen verlinken, wobei der Link als Parameter die ID der aktuellen Seite und die ID des Users enthält, um damit eine Seite anzusteuern. Die Seiten-ID benötigt man des Öfteren, um auf einer separaten Seite weitere Details darzustellen und von dort schließlich mit einem Link wieder zurückverlinken zu können.

Anzeige
Anzeige
TYPOSCRIPT – SETUP
	20.typolink.parameter = 52
	20.typolink.additionalParams = &fe_user={field:uid}&backPID={TSFE:id}
	20.typolink.additionalParams.insertData = 1

Listing 6

Wir bedienen uns bei der Bildung der URL einer starken Funktion von stdWrap und verwenden Platzhalter nach dem Muster {<Anweisung>:<Parameter>}. Damit sie nicht als Text, sondern als Anweisung, konkret als getText, interpretiert werden, muss dies noch mit insertData = 1 bekanntgemacht werden.

Nach diesem Muster lassen sich Links zur Ansteuerung von Seiten erzeugen, auf denen Plugins liegen. Die Plugins können diese(n) Parameter dann empfangen und interpretieren.

Auch bei der SQL-WHERE-Klausel in Listing 3 haben wir schon von getText Gebrauch gemacht, denn {date:<format>} liefert das aktuelle Datum im angegebenen Format, wobei U dort für das Format Unix Timestamp [4] steht. Im Klartext bedeutet der Ausdruck also: Liefere alle Datensätze, bei denen der letzte Login größer (also neuer, aktueller) vom aktuellen Zeitpunkt 864.000 Sekunden (= 10 Tage) rückwärts gerechnet ist.

Anzeige
Anzeige

Der kleine Unterschied

stdWrap Eigenschaft Wirkung
field = uid

wrap = userid=|

Übernimm den Inhalt aus der Spalte uid der letzten Datenbankabfrage und umschließe ihn mit userid=|.
data = field:uid

wrap = userid=|

Werte den getText in data aus und umschließe ihn.
current = userid={field:uid}

current.insertData = 1

Lade den Content mit der Zeichenkette aus current und ersetze alle Vorkommen von {…} als getText.

Die Ausdrücke in dieser Tabelle bewirken scheinbar alle das Gleiche. In dieser einfachen Form ist das tatsächlich so.

Interessant wird es nun, wenn man sich die Unterschiede vor Augen führt. Version 1 und 2 unterscheiden sich nur unwesentlich. Die zweite benutzte getText und ist damit noch einen Tick universeller, kann man damit doch auch in jedem Kontext die aktuelle Seiten-ID, die Informationen aus der Rootline und Ähnliches erfragen. Das dritte Beispiel ist viel kompakter und flexibler. Man kann mehrere getText-Anweisungen in eine Zeile schreiben. Wir werden im nächsten Teil tiefer darauf eingehen.

Fazit und Ausblick

Wir haben mit wenigen Zeilen TypoScript eine Userliste entwickelt, die in PHP verfasst mindestens den doppelten bis dreifachen Umfang eingenommen hätte. Gleichwohl gibt es natürlich Situationen, in denen sich dieses Verhältnis schnell umkehren kann. Die Auswirkungen einer getroffenen Entscheidung vorauszusehen und zu planen kann manchmal nicht ganz einfach sein. Einige der Beschränkungen des CONTENT-Objekts sind offensichtlich. Systemtabellen oder nicht-TYPO3-Tabellen zu befragen, ist unmöglich [5], lange Listen möchte man gern durchblättern können und die propagierte Trennung von Code, Inhalt und Design ist uns auch etwas verloren gegangen.

Die meisten der oben genannten Beschränkungen von CONTENT werden wir im nächsten Teil mit einer von mir entwickelten Extension aufheben. Außerdem werden als Fingerübung weitere stdWrap-Eigenschaften wie Bedingungen und Umwandlungen eingesetzt, wenn wir die Profilseite für einen User dynamisch erzeugen.

Mehr zu diesem Thema
Fast fertig!

Bitte klicke auf den Link in der Bestätigungsmail, um deine Anmeldung abzuschließen.

Du willst noch weitere Infos zum Newsletter? Jetzt mehr erfahren

Anzeige
Anzeige
Schreib den ersten Kommentar!
Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!
Hallo und herzlich willkommen bei t3n!

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team von mehr als 75 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Schon jetzt und im Namen der gesamten t3n-Crew: vielen Dank für deine Unterstützung! 🙌

Deine t3n-Crew

Anleitung zur Deaktivierung
Artikel merken

Bitte melde dich an, um diesen Artikel in deiner persönlichen Merkliste auf t3n zu speichern.

Jetzt registrieren und merken

Du hast schon einen t3n-Account? Hier anmelden

oder
Auf Mastodon teilen

Gib die URL deiner Mastodon-Instanz ein, um den Artikel zu teilen.

Anzeige
Anzeige