Zum Inhalt springen

~/CodeBlog.at

TYPO3: Migration von Gridelements zu Container – Schritt für Schritt

·6 Min. Lesezeit

Veröffentlicht
Überarbeitet

Was ist neu: Aktuelle Versionen und Kompatibilität (inkl. TYPO3 14) ergänzt, Registrierungs-Code vervollständigt, Prüfung von Übersetzungen und Sortierung per CLI sowie Aufräumen nach der Migration.

Kurz & knapp

Für die Migration von Gridelements zu EXT:container registrierst du pro Grid einen Container (Registry::configureContainer()), stellst in tt_content die Grids per SQL auf den neuen CType um (gridelements_pi1 → container-<ID>) und überträgst bei den Kindelementen tx_gridelements_columns nach colPos und tx_gridelements_container nach tx_container_parent. Danach Übersetzungen mit den Container-CLI-Befehlen prüfen und die Templates als Fluid mit ContainerProcessor bauen.

Getestet mit: Original-Migration: TYPO3 10.4 → 11.5, Gridelements 9.5, Container 1.4, Code abgeglichen mit Container 4.1 (TYPO3 13.4/14.3)

Inhalt
  1. Muss ich überhaupt migrieren?
  2. Vorbereitung
  3. Schritt 1: Grid-Konfiguration übernehmen
  4. Schritt 2: Container registrieren
  5. Schritt 3: Datenbank umstellen
  6. Schritt 4: Übersetzungen und Sortierung prüfen
  7. Schritt 5: Frontend-Templates
  8. Schritt 6: Aufräumen

Lange war Gridelements (öffnet in neuem Tab) die Lösung für verschachtelte Inhaltselemente in TYPO3. Inzwischen setzen viele Projekte auf EXT:container (öffnet in neuem Tab) von b13 – schlanker, näher am Core und für aktuelle TYPO3-Versionen verfügbar. Hier zeige ich, wie ich die Migration in einem Kundenprojekt durchgeführt habe.

Muss ich überhaupt migrieren?

Extension Aktuelle Version Unterstützte TYPO3-Versionen
Gridelements 13.1 (öffentlich) 12.4, 13.4
Gridelements 14 Priority Access 14
Container 4.1 13.4, 14.3
content_defender 3.5 11.5, 12.4, 13.4

Stand: Oktober 2026, laut Packagist. Solange du auf TYPO3 12 oder 13 bleibst, läuft Gridelements weiter.

Wer bei frei verfügbaren Extensions bleiben möchte, kommt spätestens mit TYPO3 14 an Container nicht vorbei. Die Migration passt gut in ein Upgrade-Projekt, weil die Seiten danach ohnehin getestet werden.

Vorbereitung

  1. Backup von Datenbank und Dateien erstellen – und die Migration auf einem Entwicklungssystem durchführen, z. B. mit DDEV.

  2. Container installieren – Gridelements bleibt vorerst installiert, damit die Daten erhalten bleiben:

    composer req b13/container
  3. content_defender installieren, falls du – wie bei Gridelements üblich – pro Spalte erlaubte Inhaltstypen festlegen willst:

    composer req ichhabrecht/content-defender

Schritt 1: Grid-Konfiguration übernehmen

In meinem Projekt waren die Grids als Datensätze in der Datenbank angelegt. Die Konfiguration eines Grids sah so aus:

mod.web_layout.BackendLayouts {
  exampleKey {
    title = Zweispaltig (Teaser-Texte lang)
    icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif
    config {
      backend_layout {
        colCount = 2
        rowCount = 1
        rows {
          1 {
            columns {
              1 {
                name = Links
                colPos = 10
                allowed {
                  CType = header,text,textpic,image,textmedia,bullets,form_formframework
                }
              }
              2 {
                name = Rechts
                colPos = 20
                allowed {
                  CType = header,text,textpic,image,textmedia,bullets,form_formframework
                }
              }
            }
          }
        }
      }
    }
  }
}

Für den Container brauche ich daraus nur den Titel, die Beschreibung und die Spalten mit ihren colPos-Werten.

Schritt 2: Container registrieren

Die Registrierung kommt in die Datei Configuration/TCA/Overrides/tt_content.php deines Sitepackages:

<?php
// Configuration/TCA/Overrides/tt_content.php

\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\B13\Container\Tca\Registry::class)->configureContainer(
    (
        new \B13\Container\Tca\ContainerConfiguration(
            'container-5',                     // CType: container-{ID des Grids}
            'Zweispaltig (Teaser-Texte lang)', // Titel
            '',                                // Beschreibung
            [
                [
                    [
                        'name' => 'Links',
                        'colPos' => 10,
                        'allowed' => [
                            'CType' => 'header,text,textpic,image,textmedia,bullets,form_formframework',
                        ],
                    ],
                    [
                        'name' => 'Rechts',
                        'colPos' => 20,
                        'allowed' => [
                            'CType' => 'header,text,textpic,image,textmedia,bullets,form_formframework',
                        ],
                    ],
                ],
            ]
        )
    )
    // optional: eines der mitgelieferten Icons verwenden
    ->setIcon('container-2col')
);

Als CType nehme ich container- plus die ID des Grids aus der Datenbank – hier container-5. Das macht die Datenbank-Umstellung im nächsten Schritt besonders einfach. Die colPos-Werte übernehme ich aus dem Grid.

Die allowed-Einschränkungen funktionieren nur mit installiertem content_defender – ohne ihn werden sie ignoriert. Zusätzlich unterstützt content_defender disallowed und maxitems.

Schritt 3: Datenbank umstellen

Jetzt kommt der aufwendigere Teil. Vorher unbedingt das Backup prüfen!

Die Grids selbst werden zu Containern, indem nur der CType umgebaut wird:

UPDATE `tt_content`
SET `CType` = CONCAT('container-', `tx_gridelements_backend_layout`)
WHERE `CType` = 'gridelements_pi1';

Der Inhalt der Grids bekommt seine Spalte als colPos und den Container als tx_container_parent:

UPDATE `tt_content`
SET `colPos` = `tx_gridelements_columns`,
    `tx_container_parent` = `tx_gridelements_container`
WHERE `colPos` = -1;

Gridelements markiert Kindelemente mit colPos = -1. Das funktioniert auch mit verschachtelten Grids – jede Ebene wird gleich behandelt.

Schritt 4: Übersetzungen und Sortierung prüfen

Bei mehrsprachigen Seiten lohnt sich ein genauer Blick. Laut Container-Dokumentation gilt:

  • Ein Kindelement hat dieselbe pid wie sein Container.
  • tx_container_parent eines übersetzten Kindelements zeigt nicht auf den übersetzten Container, sondern auf den Original-Container der Standardsprache.
  • Die Sortierung (sorting) gilt seitenweit.

Container bringt CLI-Befehle mit, die genau solche Inkonsistenzen finden und beheben:

# Sortierung der Container-Kindelemente prüfen
vendor/bin/typo3 container:sorting

# … und z. B. auf Seite 123 korrigieren
vendor/bin/typo3 container:sorting --apply 123

# Container-Zuordnung übersetzter Kindelemente korrigieren
vendor/bin/typo3 container:fixContainerParentForConnectedMode

Ich empfehle, nach der SQL-Migration zumindest die Prüfbefehle laufen zu lassen und mehrsprachige Seiten im Backend und Frontend durchzuklicken.

Schritt 5: Frontend-Templates

Bei Gridelements wurde das Markup oft per TypoScript gebaut – so auch bei mir:

tt_content {
    gridelements_pi1.20.10.setup {
        5 < lib.gridelements.defaultGridSetup
        5 {
            columns {
                10 < .default
                10 {
                    wrap = <div class="longfacts-spalte-1">|</div>
                }

                20 < .10
                20 {
                    wrap = <div class="longfacts-spalte-2">|</div>
                }
            }

            wrap = <section id="longfacts" class="wrapper style2"><div class="inner"><div class="posts"><section class="facts-gesamt">|</section></div></div></section>
        }
    }
}

Daraus wird ein Fluid-Template. Der ContainerProcessor stellt für jede Spalte eine Variable children_<colPos> bereit:

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:layout name="Default"/>
<f:section name="Main">
    <section id="longfacts" class="wrapper style2">
        <div class="inner">
            <div class="posts">
                <section class="facts-gesamt">
                    <div class="longfacts-spalte-1">
                        <f:if condition="{children_10}">
                            <f:for each="{children_10}" as="child">
                                <f:format.raw>{child.renderedContent}</f:format.raw>
                            </f:for>
                        </f:if>
                    </div>
                    <div class="longfacts-spalte-2">
                        <f:if condition="{children_20}">
                            <f:for each="{children_20}" as="child">
                                <f:format.raw>{child.renderedContent}</f:format.raw>
                            </f:for>
                        </f:if>
                    </div>
                </section>
            </div>
        </div>
    </section>
</f:section>
</html>

Damit die Templates von Fluid Styled Content (Layouts, Partials) weiter funktionieren, definiere ich einmal eine Basis-Konfiguration für alle Container:

lib.containerElement =< lib.contentElement
lib.containerElement {
    layoutRootPaths {
        100 = EXT:fluid_styled_content/Resources/Private/Layouts
        110 = EXT:theme/Resources/Private/Layouts/Container
    }

    templateRootPaths {
        100 = EXT:fluid_styled_content/Resources/Private/Templates
        110 = EXT:theme/Resources/Private/Templates/Container
    }

    partialRootPaths {
        100 = EXT:fluid_styled_content/Resources/Private/Partials
        110 = EXT:theme/Resources/Private/Partials/Container
    }

    dataProcessing {
        10 = B13\Container\DataProcessing\ContainerProcessor
    }
}

Für jeden Container genügt dann:

tt_content.container-5 < lib.containerElement
tt_content.container-5 {
    templateName = Container-5
}

Das Template liegt in diesem Beispiel unter EXT:theme/Resources/Private/Templates/Container/Container-5.html.

Schritt 6: Aufräumen

Wenn alle Seiten korrekt aussehen:

  1. Referenzindex aktualisieren:

    vendor/bin/typo3 referenceindex:update
  2. Gridelements entfernen – inklusive des zugehörigen TypoScripts und TSconfigs:

    composer remove gridelementsteam/gridelements
  3. Im Install Tool unter Maintenance → Analyze Database Structure die nicht mehr benötigten tx_gridelements_*-Felder und -Tabellen entfernen – erst, wenn du sicher bist, dass alles migriert ist.

Und schon sind alle ehemaligen Gridelements Container-Elemente.

Häufige Fragen

Muss ich von Gridelements zu Container migrieren?

Nicht zwingend: Gridelements 13.1 unterstützt TYPO3 12.4 und 13.4. Für TYPO3 14 gibt es Gridelements derzeit nur über das kostenpflichtige Priority-Access-Programm von Coders.Care, öffentlich erst nach TYPO3 15 LTS. Wer frei verfügbare Extensions möchte, migriert spätestens mit TYPO3 14 zu EXT:container.

Welchen CType bekommt der Container?

Frei wählbar. Praktisch ist container- plus die ID bzw. der Schlüssel des bisherigen Grid-Layouts, z. B. container-5 – dann lässt sich der CType direkt per SQL aus tx_gridelements_backend_layout erzeugen.

Funktioniert die Migration auch mit verschachtelten Grids?

Ja. Die SQL-Statements stellen jedes Grid und jedes Kindelement um, unabhängig von der Verschachtelungstiefe.

Brauche ich content_defender?

Nur wenn du pro Spalte erlaubte Inhaltstypen (allowed), Verbote (disallowed) oder maxitems festlegen willst – das kann EXT:container nicht allein. content_defender unterstützt laut Packagist derzeit TYPO3 bis 13.4.

Quellen & weiterführende Links

  1. b13/container – README (Registrierung, DataProcessor, Migration, CLI) (öffnet in neuem Tab) – GitHub
  2. container_example (öffnet in neuem Tab) – GitHub
  3. EXT:container (öffnet in neuem Tab) – TYPO3 Extension Repository
  4. EXT:gridelements (öffnet in neuem Tab) – TYPO3 Extension Repository
  5. Grid Elements 14 Priority-Access-Programm (öffnet in neuem Tab) – Coders.Care
  6. EXT:content_defender (öffnet in neuem Tab) – TYPO3 Extension Repository

Geschrieben von

Christoph Schwob (öffnet in neuem Tab)

Ich bin Christoph Schwob, halbkreativer Entwickler aus Österreich und arbeite seit über 10 Jahren an und mit TYPO3. Hier sammle ich Lösungen, Code-Snippets und Notizen rund um TYPO3, macOS, Server, Homelab und alles andere.

Suche

Tippe einen Suchbegriff ein.