Typo3 Extensions - Backend Formulare und TCA Konfiguration
Einführung[Bearbeiten]
Im TCA (Table Content Array) wird definiert wie ein Feld im Backend aussieht, wie es validiert wird etc. Außerdem wird es von Extbase genutzt um sich Informationen über die Validierung zu holen.
TCA Beispiele[Bearbeiten]
Ausschnitte aus der TCA mit verschiedenen Beispiel Definitionen
File Upload Feld[Bearbeiten]
TCA - In Depth[Bearbeiten]
http://t3-developer.com/1/ext-programmierung/basics/das-tca-im-detail/
Das Table Configuration Array (TCA) ist ein mächtiges globas Array innerhalb von TYPO3 was die Datenbanktabellen genauer beschreibt und weitere Möglichkeiten über die Funktionen von sql hinaus eröffnet. Jede Datenbnaktabelle die im Backend angezeigt und bearbeitet werden soll benötigt ein TCA Array.
Ohne ein TCA Array für eine Tabelle geht in TYPO3 nichts da es die zentrale Schnittstelle zwischen Datenbank und TYPO3 darstellt. Wir brauchen also für jede Tabelle unserer Extension ein $TCA Array um die Tabelle im Backend anzuzeigen und den Tabelleninhalt in Extbase Models verfügbar zu machen.
Zusätzlich werden Tabellenrelation im TCA definiert, welche Felder in welcher Form im Backend angezeigt und wie validiert werden.
Seit TYPO3 6.1 reicht es aus, für jede Tabelle eine Datei mit dem entsprechendem TCA Array (Dateiname = Tabellenname) im Extension-Ordner Configruration/TCA zu speichern. Die Datei wird von dort automatisch geladen.
Achtung in V8 funktionieren die alten Definitionen in ext_tables.php gar nicht mehr.
Es ist also nicht mehr erforderlich (wie bis 6.1 üblich), einen Teil der TCA Definition (das ctrl Array) in die ext_tables.php zu schreiben und dann auf eine dynamische Konfiguration im TCA Ordner zu verweisen.
Vorsicht: Damit wird nur das TCA automatisch geladen. Die Variable $_EXTKEY ist nach meiner Erfahrung im Verzeichnis Configuration/TCA nicht erreichbar (Diese wird desöftern in der Zeile iconfile => ... verwendet). Die Zeilen:
...\ExtensionManagementUtility::addLLrefForTCAdescr(... und ....\ExtensionManagementUtility::allowTableOnStandardPages(...
müssen nach wie vor in der ext_tables.php eingefügt werden.
Aussehen von Backend Formularen[Bearbeiten]
Allgemeines[Bearbeiten]
Definiert im TCA Array.
$TCA['tx_myextension_domain_model_table'] = array(
'ctrl' => array(
... genrelle Anzeigeoptionen im Backend (Icon, Titel etc ...)
... generelles Verhalten der Tabelle
... Pflichtangabe für jede Tabelle
),
'interface' => array(
... Angaben wir die Tabelle im Backend angezeigt werden soll
),
'types' => array(
... Anordnung der Felder innerhalb der Backendformulare (Datensatz bearbeiten)
),
'palettes' => array(
... Hier können mehrere Felder für eine horizontale Anordnung im Formular zusammengafasst werden
),
'columns' => array(
... Für jedes Datanbankfeld werden hier die Eigenschaften festgelegt:
... Feldtyp, Relationen, Validierung
),
);
Früher (veraltet)[Bearbeiten]
In Extensions wird es in den Dateien
ext_tables.php und tca.php
festgelegt. In tca.php wird z.B. mit
..."ctrl" => $TCA["tx_pupmanager_members"]["ctrl"],... // DEPRECATED siehe oben
der Teil ctrl des TCA Arrays aus ext_tables übernommen. Man muß also nur in diesen beiden Dateien die Werte verändern um auf verschiedene Weise das Backend zu konfigurieren. Die Details findet man in:
http://typo3.org/documentation/document-library/core-documentation/doc_core_api/
Die Ebenen des Arrays sind wie folgt angelegt.
Schlüssel: ctrl[Bearbeiten]
Bereich ctrl wird immer gleich geladen die anderen BEreiche erst dynamisch. Wenn sie benutzt werden mit
t3lib_loadTCA('your_table_name');
nachladen
Level 1[Bearbeiten]
Die Schlüssel entsprechen den DB-Tabellen
Grundsätzliche Einstellungen in ext_tables.php
Level 2 und 3[Bearbeiten]
Diese beziehen sich auf die Struktur eines Tabelleneintrags (so sieht also ein Datensatz im Backend aus) und werden meist in tca.php festgelegt.
Hilfetexte[Bearbeiten]
Wenn die Extension im Builder vorbereitet ist, dann ist alles schon vorangelegt. PHP
ext_tables.php -> bekannt machen der Hilfetextdatei
t3lib_extMgm::addLLrefForTCAdescr(
'tx_meineExtension_DBTabelle',
'EXT:ExtensionKey/locallang_csh_ExtensionKey_DBTabelle.xml'
);
Schlüssel ist dann:
meinFeld.description außerdem gibt es noch meinFeld.details
Validierung von Backend Formularen[Bearbeiten]
Für Backendfelder steht der Bereich eval zur Verfügung. Dort gibt es vorgefertigte Evaluierungsmöglichkeiten. Es können auch mittels einer Extension eigene JavaScripte zur Evaluierung gebastelt werden. Eine Beispielextension steht auch zur Verfügung.
http://typo3.org/documentation/api/
['columns'][fieldname]['config'] / TYPE: "input" eval=>...
Eine Klasse für eigene Validierung einbauen[Bearbeiten]
Old School[Bearbeiten]
Nachfolgendes bezieht sich auf alte Extensions ohne Extbase, bin mir nicht sicher ob das in Extbase anders funktioniert. Folgende Schritte sind notwendig:
- Eine Klasse zur Evaluierung in der Extension anlegen in der Art: class.tx_meineextension_extraeval1
- Diese Klasse enthält zwei Funktionen. Eine für die Evaluierung per JavaScript bei der Eingabe und eine php Evaluierung nachdem der Datensatz gespeichert wurde. Unten steht die Beispielklasse aus der typo3.org API Dokumentation aus; sie fügt den eingegebenen Werten die unten gezeigten Strings hinzu.
- Die Funktion returnFieldJS() gibt den JavaScript Code zurück. Im JavaScript steht die Variable value zur Verfügung die den Wert des Feldes enthält.
- Die Funktion evaluateFieldValue ($value, $is_in, &$set) hat folgende Übergabewerte: $value ist der Feldinhalt, $is_in enthält die Werte aus der Typo3 Eval Funktion is_in (Filtert Zeichen aus), &$set ist Boolean und legt fest ob der Wert in die Datenbank geschrieben wird oder nicht. Wird per Referenz übergeben.
- In ext_localconf.php muß die Klasse registriert werden damit sie zur Verfügung steht
- In tca.php kann nun den Backendeingabefeldern die Evaluierung zugewiesen werden.
class.tx_exampleextraevaluations_extraeval1
<?php
class tx_exampleextraevaluations_extraeval1 {
function returnFieldJS() {
return '
return value + " [added by JS]";
';
}
function evaluateFieldValue($value, $is_in, &$set) {
return $value.' [added by PHP]';
}
}
?>
ext_localconf.php
... # Register new evaluation method in the $TYPO3_CONF_VARS['SC_OPTIONS']['tce']['formevals'] array. $TYPO3_CONF_VARS['SC_OPTIONS']['tce']['formevals']['tx_exampleextraevaluations_extraeval1'] = 'EXT:example_extraevaluations/class.tx_pupmanager_extraeval1.php';
Beispiel zum Aufruf in tca.php
... 'eval' => 'trim,tx_exampleextraevaluations_extraeval1', ...
Felder in Abhängigkeit von anderen anzeigen oder verstecken[Bearbeiten]
Möglichkeit 1: in der Felddefinition[Bearbeiten]
Für jedes Feld das eventuell versteckt werden soll, wird eine Bedingung angegeben Im TCA (tca.php) unter
['columns'][fieldname] displayCond
Beispiele:
This example will require the field named "tx_templavoila_ds" to be true, otherwise the field for which this rule is set will not be displayed: 'displayCond' => 'FIELD:tx_templavoila_ds:REQ:true', This example requires the extension "static_info_tables" to be loaded, otherwise the field is not displayed. (This is useful if the field makes a look-up on a table coming from another extension!) 'displayCond' => 'EXT:static_info_tables:LOADED:true', Wie man sieht ist der String mit : in verschiedene Bereiche aufgeteilt. Teil 1 ist der Regeltyp. FIELD bezieht sich z.B. auf ein Feld im selben Datensatz. Je nachdem was im ersten Teil steht kann man weitere Teile angeben. http://typo3.org/documentation/document-library/core-documentation/doc_core_api/4.1.0/view/4/2/
Möglichkeit 2: mit Paletten[Bearbeiten]
Möglichkeit 3:[Bearbeiten]
Reihenfolge der Felder im Backend[Bearbeiten]
['types'][key]
Beispiel:
'types' => Array (
'0' => Array('showitem' => 'hidden;;1, type, title, test_template'),
The key "showitem" lists the order in which to define the fields: "hidden, type, title, test_template"
(nicht mit showRecordFieldList verwechseln - das legt nur Fest was überhaupt angezeigt wird.
Default Werte in Backend-Feldern[Bearbeiten]
useColumnsForDefaultValues
Wenn Daten auf komplexere Weise im Backend manipuliert werden sollen geht es z.B. so:
TYPO3 Hook im Backend beim Speichern von Datensätzen
oder
Backend: Default-Werte per TSConfig setzen
Tabs in Backend Formularen[Bearbeiten]
dividers2tabs(in types)
Funktion nach dem Speichern eines Datensatzes im Backend ausführen[Bearbeiten]
Kurzversion für Details siehe nachfolgender Abschnitt.
ext_localconf.php (Wenn nicht vorhanden Erstellen) Folgendes einfügen
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = 'EXT:ext_name/hooks/class.tx_ext_name_tcemainhooks.php:tx_ext_name_tcemainhooks';
Neue Datei
class.tx_ext_name_tcemainhooks.php
<?php
class tx_gbglossary_tcemainhooks {
function processDatamap_preProcessFieldArray(&$FieldArray, $table, $id, &$tceobj) {
debug($FieldArray,"FieldArray");
debug($table,"Table");
debug($id,"id");
debug($tceobj,"tceobj");
}
}
?>
Funktionen vor oder nach der Backendeingabe ausführen[Bearbeiten]
Verwendete Dateien:
ext_localconf.php (Hier wird der Hook registriert) class.tx_myExtension_post-or whatever.php (Hier kommt der auszuführende Code)
Dies kann mit Hooks realisiert werden.
http://typo3.org/development/articles/how-to-use-existing-hooks/page/2/
http://www.koller-webprogramming.ch/tipps-tricks/typo3-extension-entwicklung/hook-im-backend/
Daten die vom Backend übermittelt werden werden in der Klasse t3lib_tcemain bearbeitet. Das wäre der geeignete Ort um einzugreifen. Diese liegt in t3lib/class.t3lib_tcemain.php. Jetzt wäre es natürlich blöde in den Core Dateien herumzufuhrwerken. Aber es gibt ja das Hook Konzept, mit dem ein Programmierer Schnittstellen bereitstellen kann um die Funktionalität zu erweitern. Netterweise hat ein lieber Core Programmierer schon zwei Hooks vorgesehen die vor bzw. nachdem speichern der Daten im Backend genutzt werden können.
Es gibt 2 Möglichkeiten den Hook zu nutzen. callUserFunction und the getUserObj. Wobei zweitere die schickere (weil ansatzweise Objektorientiert) ist. Auf die callUserFunction gehen wir zunächst hier nicht ein.
Die getUserObj Methode stellt uns auch der folgende Hook zur Verfügung.
Schauen wir uns den Code des Post Process Hooks in der Datei class.t3li_tcemain.php an:
// Hook: processDatamap_postProcessFieldArray
reset($hookObjectsArr);
while (list(,$hookObj) = each($hookObjectsArr)) {
if (method_exists ($hookObj, 'processDatamap_postProcessFieldArray')) {
$hookObj->processDatamap_postProcessFieldArray ($status, $table, $id, $fieldArray, $this);
}
}
Im obigen Code-Schnipsel aus TCE-Main wird ein Array $hookObjectsArr übergeben und eine Methode processDatamap_postProcessFieldArray wird aufgerufen wenn dieses Existiert.
Klasse schreiben und Hook Funktion überschreiben[Bearbeiten]
Wir schreiben einfach eine Klasse in der wir die Funktion processDatamap_postProcessFieldArray überschreiben und hier unserer eigene Funktion bereitstellen.
Registrieren des Hooks[Bearbeiten]
in der Core Datei wird die Funktion im Globalen Array $TYPO3_CONF_VARS registriert. Genauso müssen wir das mit unserer neuen Funktion machen. Die neuen Methoden Registrieren wir in ext_localconf.php
Typo 3 hat seine Klasse so registriert:
process_datamap function des Typo3 Core (obige Datei):
// First prepare user defined objects (if any) for hooks which extend this function:
$hookObjectsArr = array();
if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'])) {
foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'] as $classRef) {
$hookObjectsArr[] = &t3lib_div::getUserObj ($classRef);
}
}
Unserer neue Klasse soll genauso eine Instanz des Objekts in genau diesem Array $hookObjectsArr sein.
Deshalb registrieren wir in der Datei ext_localconf.phpunserer Extension unsere Datei indem wir die Funktion genau wie oben im Array aufnehmen:
$GLOBALS ['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = 'tx_myextension_tcemainprocdm';
2.2. Klassendatei laden[Bearbeiten]
Jezt müssen wir noch aufpassen das die Klassendatei auch geladen wird wenn sie benötigt wird. Dazu können wir ein require_once statement in ext_tables.php unserer Extension hinzufügen oder besser folgendes machen.
2.3. Laden und Registrieren der Klasse gleichzeitig[Bearbeiten]
Die getUserObj Methode erlaubt uns die beiden Schritte gleichzeitig auszuführen. Das können wir dann beides in ext_localconf.php machen. Dann sieht die Zeile von vorhin etwas anders aus:
$GLOBALS ['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = 'EXT:myextension/class.myextension_tcemainprocdm.php:tx_myextension_tcemainprocdm';
Das hat zudem den Vorteil, das die Klasse nur dann aufgerufen wird wenn sie auch benötigt wird.
Another great advantage of this method is that your file will only be included if it's really used! postProcessFieldArray" in der Rubrik "processDatamap
Wie Programmiert man ?[Bearbeiten]
Für die Programmierung steht die Typo3 Core Engine zur Verfügung (TCE)
Das Konzept:
When you are using TCE from your backend applications you need to prepare two arrays of information which contain the instructions to TCEmain of what actions to perform. They fall into two categories: Data and Commands.
"Data" is when you want to write information to a database table or create a new record.
"Commands" is when you want to move, copy or delete a record in the system.
The data and commands are created as multidimensional arrays and to understand the API of TCEmain you simply need to understand the hierarchy of these two arrays.
Commands Array ($cmd):
Syntax:
$cmd[ tablename ][ uid ][ command ] = value
Unsere Funktion: Wird aufgerufen wenn Datensatz gespeichert wird Parameter:
$status->update oder new, $table -> die im Moment bearbeitete Tabelle, $id-> bei status new ein Zufallscode Newxxxxx sonst die uid des Datensatzen, &$fieldArray -> hier kann man einen Wert aus dem gerade zu speichernden Datensatz überschreiben $reference -> das komplette cObj
class tx_myextension_tcemainprocdm {
function processDatamap_postProcessFieldArray ($status, $table, $id, &$fieldArray, &$this) {
// here comes the code
}
}