Zum Inhalt springen

Ziel

Wir richten uns zwei neue Seiteneigenschaften ein: Ein weiteres Textfeld zur freien Verfügung sowie eine eigene Checkbox.

  • Das Textfeld wird sowohl in der Originalsprache als auch bei alternativen Seitensprachen individuell pflegbar sein.
  • Bei der Checkbox erweitern wir das Verhalten bei Übersetzungen: Der Status (aktiv/inaktiv) wird auf übersetzte Seiten vererbt und kann dort bei Bedarf überschrieben werden.

Das Tutorial gilt für alle TYPO3-Versionen ab 9.5! In älteren TYPO3-Versionen wurde für übersetzte Seiten noch die Datenbanktabelle pages_language_overlay benötigt. Im Internet Archive (Wayback Machine) findet ihr dieses Tutorial mit den notwendigen Ergänzungen für TYPO3 v8 und früher.

tl;dr

Die fertige Extension findet ihr auf Github:

Demo herunterladen

Dateistruktur

Um die Datenbanktabellen in TYPO3 erweitern zu können, bedarf es einer bestimmten Ordner- und Dateistruktur in unserer Extension:

  • In Configuration/TCA/Overrides werden neue Felder für bestehende Tabellen konfiguriert. Aus Gründen der Verständlichkeit sollten die Dateien den Namen der Datenbanktabelle tragen.
  • In Resources/Private/Language habe ich die Bezeichnungen für das Backend in englischer und deutscher Sprache hinterlegt. Dies ist der saubere Ansatz, man könnte aber auch die Namen (ohne Übersetzung) direkt ins TCA schreiben.
  • Extension.svg ist als Icon im Extension Manager zu sehen.
  • composer.json ermöglicht die Installation der Extension mit composer (wird in diesem Tutorial nicht näher erklärt).
  • ext_emconf.php enthält die Extension-Konfiguration. Ohne diese Datei kann die Extension in TYPO3 nicht installiert werden.
  • In der ext_tables.sql erweitern wir die Datenbank von TYPO3 mit SQL.

Die Extension habe ich in diesem Fall pages_addfields genannt.

Grundsätzliche Konfiguration der Extension

In der Konfigurationsdatei ext_emconf.php finden sich Titel und Beschreibung der Extension, die Versionsnummer, Angaben zum Autor und ggf. Abhängigkeiten, z.B. zur TYPO3-Version.

ext_emconf.php

<?php

$EM_CONF[$_EXTKEY] = [
    'title' => 'Additional pages field(s)',
    'description' => 'Provides a basic example how to extend TYPO3 pages with your own fields.',
    'category' => 'example',
    'author' => 'Sebastian Klein',
    'author_email' => 'sebastian@sebkln.de',
    'state' => 'test',
    'version' => '3.0.0',
    'constraints' => [
        'depends' => [
            'typo3' => '11.5.0-12.4.99',
        ],
        'conflicts' => [
        ],
        'suggests' => [
        ],
    ],
];

Neue Datenbankfelder anlegen

Über die Datei ext_tables.sql werden die neuen Datenbankfelder ergänzt. Es muss hier der Befehl CREATE TABLE verwendet werden – TYPO3 erkennt bei der Installation der Extension, ob die Tabelle bereits existiert und fügt der bestehenden Tabelle dann nur die neuen Felder hinzu.

Die Verwendung des Extension-Keys im Feldnamen (hier: tx_pagesaddfields) ist nicht notwendig, vermeidet aber Kollisionen mit anderen Extensions, die ggf. Felder gleichen Namens anlegen könnten.

ext_tables.sql

#
# Modifying pages table
#
CREATE TABLE pages (
    tx_pagesaddfields_customtext varchar(255) DEFAULT '' NOT NULL,
    tx_pagesaddfields_customcheckbox TINYINT(1) UNSIGNED DEFAULT '0' NOT NULL
);

Falls nachträglich Änderungen am SQL vorgenommen werden, muss die Extension einmal de- und re-installiert werden, damit TYPO3 die Anpassungen erkennt und übernimmt.

Das Table Configuration Array: $GLOBALS['TCA']

Damit TYPO3 die Datenbankfelder verwendet, müssen sie über das TCA bekannt gemacht und konfiguriert werden.

Im ersten Schritt werden die neuen Felder konfiguriert: als Input-Feld und Checkbox. Ein ganz kurzer Überblick über die Konfiguration:

  • label: der Name des Feldes im Backend. Könnte hartkodiert hinterlegt werden, hier wird aber die locallang.xlf verwendet.
  • exclude: wenn gesetzt, gehört dieses Feld zu den sogenannten "Erlaubten Ausschlussfeldern", die erst über eine Backend-Benutzergruppe editierbar gemacht werden müssen.
  • config: die Art des Feldes. Hier verwenden wir ganz simple Einstellungen für unsere Felder, diese ließen sich aber auch erweitern.
    Beachtet bei der Checkbox die Einstellung allowLanguageSynchronization: sie ergänzt das eingangs beschriebene Verhalten bei Übersetzungen.

Anschließend fügen wir die Felder über die TYPO3 API-Methode addTCAcolumns der bestehenden Tabelle hinzu. Mit addToAllTCAtypes lassen wir die Felder im TCEFORM erscheinen. Zuletzt fügen wir unsere neue Palette den Seiteneigenschaften hinzu.

Configuration/TCA/Overrides/pages.php

<?php
defined('TYPO3') or die(); // use 'TYPO3_MODE' in TYPO3 versions below v11

// Configure new fields:
$fields = [
    'tx_pagesaddfields_customtext' => [
        'label' => 'LLL:EXT:pages_addfields/Resources/Private/Language/locallang_db.xlf:pages.tx_pagesaddfields_customtext',
        'exclude' => 1,
        'config' => [
            'type' => 'input',
            'max' => 255
        ],
    ],
    'tx_pagesaddfields_customcheckbox' => [
        'exclude' => 1,
        'label' => 'LLL:EXT:pages_addfields/Resources/Private/Language/locallang_db.xlf:pages.tx_pagesaddfields_customcheckbox',
        'config' => [
            'type' => 'check',
            'default' => 0,
            'behaviour' => [
                'allowLanguageSynchronization' => true
            ]
        ]
    ]
];

// Add new fields to pages:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages', $fields);

// Make fields visible in the TCEforms:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
    'pages', // Table name
    '--palette--;LLL:EXT:pages_addfields/Resources/Private/Language/locallang_db.xlf:pages.palette_title;tx_pagesaddfields',
    // Field list to add
    '1', // List of specific types to add the field list to. (If empty, all type entries are affected)
    'after:nav_title' // Insert fields before (default) or after one, or replace a field
);

// Add the new palette:
$GLOBALS['TCA']['pages']['palettes']['tx_pagesaddfields'] = [
    'showitem' => 'tx_pagesaddfields_customcheckbox,tx_pagesaddfields_customtext'
];

Lokalisierung der Backend-Labels

Die Verwendung der Lokalisierungs-Dateien hat nichts mit der Ausgabe im Frontend zu tun. Vielmehr geht es hier um die Mehrsprachigkeit im Backend. Die Labels, also die Benennung unserer Felder, können auf diese Weise für fremdsprachige Backend-Benutzer übersetzt werden.

Verlinkt wird die Sprachdatei – wie oben gesehen – mit LLL:EXT:pages_addfields/Resources/Private/Language/locallang_db.xlf:, nach dem Doppelpunkt folgt die ID des lokalisierten Inhalts. Bei gewählter Fremdsprache Deutsch im Backend sucht TYPO3 nach der Datei mit vorangestelltem Kürzel de. und der Übersetzung im target-Element.

Ab TYPO3 12.0 gibt es die neue Option$GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['requireApprovedLocalizations']. Standardmäßig ist diese aktiv. Als Folge müsst ihr bei euren XLIFF-Übersetzungen das Attribut approved="yes" ergänzen.

Resources/Private/Language/locallang_db.xlf

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<xliff version="1.0">
    <file source-language="en" datatype="plaintext" original="messages" date="2016-06-18T12:03:24Z"
          product-name="pages_addfields">
        <header/>
        <body>
            <trans-unit id="pages.palette_title">
                <source>My custom fields</source>
            </trans-unit>
            <trans-unit id="pages.tx_pagesaddfields_customtext">
                <source>Custom text field</source>
            </trans-unit>
            <trans-unit id="pages.tx_pagesaddfields_customcheckbox">
                <source>Custom checkbox</source>
            </trans-unit>
        </body>
    </file>
</xliff>

Resources/Private/Language/de.locallang_db.xlf

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<xliff version="1.0">
    <file source-language="en" datatype="plaintext" original="messages" date="2016-06-18T12:03:24Z"
          product-name="pages_addfields" target-language="de">
        <header/>
        <body>
            <trans-unit id="pages.palette_title" approved="yes">
                <source>My custom fields</source>
                <target>Meine benutzerdefinierten Felder</target>
            </trans-unit>
            <trans-unit id="pages.tx_pagesaddfields_customtext" approved="yes">
                <source>Custom text field</source>
                <target>Benutzerdefiniertes Textfeld</target>
            </trans-unit>
            <trans-unit id="pages.tx_pagesaddfields_customcheckbox" approved="yes">
                <source>Custom checkbox</source>
                <target>Benutzerdefinierte Checkbox</target>
            </trans-unit>
        </body>
    </file>
</xliff>

Fertig. Was jetzt?

Wie ihr die neuen Felder nutzt, bleibt euch überlassen. Ihr könntet beispielsweise die Ausgabe des Textfelds davon abhängig machen, ob die Checkbox gewählt wurde:

10 = TEXT
10.field = tx_pagesaddfields_customtext
10.if.isTrue.field = tx_pagesaddfields_customcheckbox