Der erste Artikel der Reihe TCA beschäftigt sich mit den Grundprinzipien des TCA von TYPO3 und versucht Grundlagen für den erstmaligen Umgang damit zu vermitteln. Abschließend wird ein kleines Tutorial die Vorgehensweise der Erweiterung von Datenstrukturen in TYPO3 verdeutlichen. Spätere Artikel werden sich mit der Erstellung von Nutzerfunktionen (userFunc) und komplexeren Tabellenstrukturen (MM) beschäftigen.
Das Table Configuration Array (TCA) kommt als flexibles Grundgerüst des TYPO3-Backends (BE) zum Einsatz und stellt damit eine mächtige Waffe für Erweiterungen dar. Dahinter verbirgt sich ein konfiguratives Multi-Array, das die globale Verwaltung von Datenstruktur, -beziehung und -darstellung von BE-Bearbeitungsmasken erlaubt. Es handelt sich also “lediglich” um eine persistente Konfiguration, die im BE über die TYPO3-Core-Engine (TCE) zum Leben erweckt wird (siehe Script: t3lib/class.t3lib_tcemain.php). Für die Grundeinstellung von wichtigen System-Tabellen wie pages, fe_groups, be_users etc. liegt bereits eine Basiskonfiguration in folgendem Script vor: t3lib/stddb/tables.php. Natürlich lassen sich auch diese individuell und sauber über lokale Extensions erweitern und verändern.
Wie bei jedem Konfigurations-Array, wird man sich anfangs in die Array-Struktur einlesen müssen um damit arbeiten zu können. Sobald man Grundaufbau und Wirkungsweise verinnerlicht hat, geht die Arbeit mit dem TCA jedoch unfassbar schnell von der Hand. Um einen ersten Eindruck vom Aufbau des TCA zu bekommen, lohnt es sich die Basiskonfigurationen von TYPO3 zu lesen und mit denen aus dem TCA-Browser im Konfigurations-Modul “Konfiguration” unter Menü “$TCA (Array für Tabellenkonfiguration)” zu vergleichen. Hier wird das globale TCA gesammelt und die extrahierte Konfiguration leicht verständlich dargestellt.
Die erste Ebene stellt den Namen der entsprechenden Datenbanktabelle unter TYPO3 dar. Im Beispiel wurde “be_groups” ausgewählt und die “columns”-Ebene aufgeklappt. Wie man unschwer erkennt, erscheinen hier die der Tabelle zugehörigen Datenbankfelder. Unter diesen befindet sich der Kern der Angelegenheit: Die Konfiguration von Darstellung und Datenverarbeitung des jeweiligen Formularfelds im BE. Bevor darauf näher eingegangen wird, ist es ratsam die übrigen Elemente vorzustellen. Unter “ctrl” verbirgt sich die Grundkonfiguration der ausgewählten Tabelle, wie zum Beispiel das Label für die Darstellung der Tabelle im List-Modul. Das “interface”-Element erlaubt die Konfiguration der Datenauflistung im BE. Hier kann unter anderem die Anzahl der gelisteten Datensätze im List-Modul konfiguriert werden. Analog dazu, könnte bei manchen auch das Element “feinterface” erscheinen. Einst für das Frontend zuständig, ist es jedoch seit dem neuen Frontend-Editing obsolet geworden. Das Element “types” behandelt zum einen in welcher Reihenfolge Formularfelder einer Maske dargestellt werden, zum anderen welche Formular-Maske bei welchem Typ erscheint. Das Typ Feld wird unter “ctrl” registriert und stellt in der Regel ein einfaches Selekt-Feld dar. Unter “types” wird dann konfiguriert welche Felder bei welchem Wert vom Typ-Feld dargestellt werden. Das letzte Element “palettes” fehlt im Bild, da es schlichtweg nicht erstellt ist bzw. notwendig war für “be_groups” Formulare. Es erlaubt Formularfelder der Übersichtlichkeit wegen in Teilbereiche zusammenzufassen.
Über das Kickstarter-GUI lassen sich sehr schnell vorhandene Tabellen-Konfigurationen erweitern und eigene definieren. Es ist demnach ratsam mit diesem Werkzeug “herumzuspielen” und die automatisch erstellten Scripte zu studieren. Dem Spaß sind jedoch sehr schnell die Grenzen gesetzt und es wird notwendig das TCA manuell zu scripten. Für die eigene Extension ist es mindestens notwendig die ext_tables.php zu definieren, um neue TCA-Definitionen unter TYPO3 zu regisitrieren. Sobald neue Felder bzw. Tabellen notwendig sind, wird eine weitere Datei mit SQL-Definitionen benötigt: ext_tables.sql.
<?php # exemplary content of ext_tables.php if (!defined ('TYPO3_MODE')) { die ('Access denied.'); } $TCA['tx_extkey_messages'] = array ( 'ctrl' => array ( 'title' => 'LLL:EXT:extkey/locallang_db.xml:tx_extkey_messages.title', 'label' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', 'default_sortby' => 'ORDER BY crdate', 'delete' => 'deleted', 'enablecolumns' => array ( 'disabled' => 'hidden', ), 'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY).'tca/tx_extkey_messages.php', 'iconfile' => t3lib_extMgm::extRelPath($_EXTKEY).'icons/icon_tx_extkey_messages.gif', ), ); ?>
Das Listing definiert den “ctrl”-Abschnitt einer neuen Tabelle namens “tx_extkey_messages”. Im Beispiel wurde absichtlich eine sinnvolle Namenskonvetion für die Tabellenbezeichnung verwendet, um die Tabellen-Zugehörigkeit direkt am Namen zu verdeutlichen. Der Key “title” zeigt auf den XML-Index “extkey.tx_extkey_messages” der Lokalisierungs-Datei “locallang_db.xml” im Extension-Verzeichnis.
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <!-- exemplary content of locallang_db.xml --> <T3locallang> <meta type="array"> <type>database</type> <description>Language labels for database tables/fields belonging to extension 'extkey'</description> </meta> <data type="array"> <languageKey index="de" type="array"> <label index="extkey.tx_extkey_messages">Nachrichten</label> <!-- ... --> </languageKey> <!-- ... --> </data> </T3locallang>
Der Vorletzte Key “dynamicConfigFile” im Abschnitt “ctrl” der Tabellenkonfiguration gibt den Pfad zum hauptsächlichen TCA an. Diese Kapselung in ein separates TCA Verzeichniss ist schwer zu empfehlen, da sich das TCA sehr schnell ins endlose streckt und man sich in den Wahnsinn scrollt. Unser simples Beispiel soll ein TCA-Interface für Nachrichten im BE zur Verfügung stellen. Dafür sind mindestens zwei Eingabefelder notwendig: Titel und Nachricht. Diese Felder werden nun über das TCA konfiguriert:
<?php # exemplary content of tca/tx_extkey_messages.php if (!defined ('TYPO3_MODE')) { die ('Access denied.'); } $TCA['tx_extkey_messages'] = array ( 'ctrl' => $TCA['tx_extkey_messages']['ctrl'], 'interface' => array ( 'showRecordFieldList' => 'title,message' ), 'columns' => array ( 'title' => array ( 'exclude' => 1, 'label' => 'LLL:EXT:extkey/locallang_db.xml:tx_extkey_messages.title', 'config' => array ( 'type' => 'input', 'size' => '10' ) ), 'message' => array ( 'exclude' => 1, 'label' => 'LLL:EXT:extkey/locallang_db.xml:tx_extkey_messages.message', 'config' => array ( 'type' => 'text', 'cols' => '30', 'rows' => '5', ) ), ), 'types' => array ( '0' => array('showitem' => 'text,message') ), ); ?>
Wie man erkennt, wird das TCA neu definiert und die bereits konfigurierte “ctrl”-Sektion in das aktuelle Array gemapped. In der “columns”-Ebene sind die Felder “title” und “message” konfiguriert. Hier wird zum Beispiel der Typ des Feldes angegeben: Input, Text, Check, Radio, Select, Group, None, Passthrough, User, Flex. Hierzu bitte die TYPO3 Doku nachlesen, da eine Erläuterung der Funktionsweise den Rahmen sprengen würde.
Die Konfiguration ist getan, doch das wichtigste wurde vergessen: ext_tables.sql. In dieser wird die DB-Tabelle letztendlich angelegt.
# exemplary content OF ext_tables.SQL # # TABLE STRUCTURE FOR TABLE 'tx_extkey_messages' # CREATE TABLE tx_extkey_messages ( uid INT(11) NOT NULL AUTO_INCREMENT, pid INT(11) DEFAULT '0' NOT NULL, tstamp INT(11) DEFAULT '0' NOT NULL, crdate INT(11) DEFAULT '0' NOT NULL, cruser_id INT(11) DEFAULT '0' NOT NULL, deleted tinyint(4) DEFAULT '0' NOT NULL, hidden tinyint(4) DEFAULT '0' NOT NULL, title tinytext, message text, PRIMARY KEY (uid), KEY parent (pid) );
Nicht vergessen die DB-Änderungen im Extensionmanager auszulösen und die Lokalisierung von “title” und “message” zu definieren.
Interessante Literatur:
Jim

Muss UTF-8 nicht auch in der DB Tabelle gesetzt werden?
@Waldemar: Hm, gute Frage! Kommt drauf an, wie schlau sich TYPO3 beim Einlesen der “locallang_db.xml” anstellt bzw. diese verarbeitet. Aber sicher ist sicher, also lieber auch im TCA auf UTF-8 einstellen.
Grüße, Jim.