Kontrollieren Sie Ihr Datenmodell und Ihre URLs, und die Migration bleibt einfach. Dieses Handbuch bietet einen praktischen Weg von Drupal 11 zu TYPO3 13, saubere JSON/CSV-Exporte, präzise Zuordnungen, Twig→Fluid-Anleitungen, sichere 301-Weiterleitungen und wiederholbare Importe, denen Sie vertrauen können.
- Drupal-Entitäten → TYPO3-Datensätze und endgültige Slugs zuordnen.
- TYPO3 13 Setup auswählen (Sites, Sprachen, Seitenbaum).
- Export über JSON:API (oder CSV über Views); Dateien kopieren.
- HTML/Assets normalisieren; Templates angleichen (Twig→Fluid).
- Kategorien, Seiten/Datensätze, Medien und 301er importieren.
- Anzahl, Links, SEO überprüfen; live gehen.
2) Minimale, genaue Kartierung
| Drupal | Beispiel | TYPO3 Ziel | Hinweise |
| Node: Basisseite | /about | Seite + tt_content | Statischer Inhalt als Text-/Bildelemente. |
| Node: Artikel/Blog | /blog/foo | Datensatz (z.B. EXT:news) oder Seite | Bevorzugen Sie Datensätze für Listen/Filter. |
| Taxonomiebegriff | „Veranstaltungen“ | sys_category | Behalten Sie Slugs bei; beziehen Sie sich auf Seiten/Datensätze. |
| Benutzer | Redakteure | be_users / be_groups (Redakteure); fe_users / fe_groups (Seitenbenutzer) | Trennen Sie Back-Office und Front-Office. |
| Datei | /sites/default/files/* | FAL (sys_file + sys_file_reference) | Behalten Sie Dateinamen/Ordner zur Rückverfolgbarkeit bei. |
Verstehen Sie Ihre Drupal Feature Anforderungen
Verwenden Sie die Migration, um den Umfang zu reduzieren. Markieren Sie nur das, was Sie wirklich in TYPO3 benötigen.
| Funktion | Prüfen | TYPO3-Fähigkeit |
| Personalisierung | ☐ | Über Erweiterungen/Integrationen |
| eCommerce | ☐ | ext:aimeos oder ext:commerce |
| Multi-Site | ☐ | Native Sites-Unterstützung |
| Rollen/Berechtigungen | ☐ | Granulare BE/FE-Gruppen |
| Headless | ☐ | EXT:headless/benutzerdefinierte APIs |
| Mehrsprachigkeit | ☐ | Natives Mehrsprachensystem |
| Workflow | ☐ | Workspaces (Entwurf/Überprüfung/Versionierung) |
| Medien | ☐ | FAL mit Speicher/Metadaten |
| Formulare | ☐ | ext:form mit Editor |
| Barrierefreiheit | ☐ | WCAG-freundliche Ausgabe (Templating) |
| CLI | ☐ | Kern und helhum/typo3-console |
3) Export aus Drupal (JSON oder CSV)
A) JSON:API (empfohlen und wiederholbar)
- Inhalt: /jsonapi/node/{bundle} (z.B. Seite, Artikel)
- Verwenden Sie ?include=field_image,uid,field_tags, um Beziehungen abzurufen.
- Verwenden Sie ?page[limit]=N für die Paginierung; exportieren Sie pro Sprache mit filter[langcode]=….
- Taxonomie: /jsonapi/taxonomy_term/{vocabulary}
- Dateien: /jsonapi/file/file → verwenden Sie attributes.uri.url für die Download-URL.
- Aliase (für 301s): /jsonapi/path_alias/path_alias → behalten Sie Quelle, Alias, langcode.
B) Ansichten → CSV (abgestimmt auf Ihren Importeur in §6B)
- Erstellen Sie eine Drupal-Ansicht pro Entität (Seiten, Artikel, Kategorien, Benutzer, Weiterleitungen, Dateien).
- Fügen Sie stabile Spalten ein: external_id (UUID), Slugs, Titel, HTML-Felder, Daten, Autor-E-Mail, Kategorie-Slugs, Bild-URL(s), Alias-Quellen/Ziele.
- Halten Sie die Spaltennamen konsistent mit Ihrem TYPO3 CSV-Importeur, um Upserts und Wiederholungen zu ermöglichen. (Kein Code hier—nur die Spezifikationsausrichtung.)
Rollenabbildungsschnappschuss
| Drupal-Rolle | TYPO3-Äquivalent |
| Administrator | Backend-Admin-Benutzer |
| Authentifizierter Benutzer | Frontend-Benutzer (fe_users) |
| Anonym | Anonymer Frontend-Zugang |
| Benutzerdefinierte Rollen | Benutzerdefinierte BE/FE-Gruppen |
4–5) Inhalt normalisieren & Vorlagen neu erstellen (Twig → Fluid)
- HTML: Entfernen Sie Drupal-spezifische Filter; konvertieren Sie Einbettungen in reines HTML oder geplante Inhaltselemente.
- Medien: Kopieren Sie Binärdateien nach fileadmin/migrated/...; behalten Sie die Originaldateinamen bei; bereiten Sie eine alte-URL → neuer-Pfad-Karte vor.
- Taxonomien: Erstellen Sie sys_category aus dem Export vor; verwenden Sie Slugs, wo möglich.
- Benutzer: Importieren Sie nur benötigte Redakteure/Seitenbenutzer; ordnen Sie sie BE/FE-Gruppen zu.
Drupal Twig → TYPO3 Fluid Grundlagen
- Layouts/Partials: Twig {% include %} → Fluid .
- Schleifen/Bedingungen: Twig {% for %} / {% if %} → Fluid / .
- URLs/Assets: Ersetzen Sie file_url() und feste Pfade durch FAL-gesteuerte Helfer und -View-Helper.
- Menüs: Drupal-Menüs → TYPO3-Menü-Rendering aus dem Seitenbaum (TypoScript DataProcessors + Fluid).
- Übersetzungen: Halten Sie Sprachschlüssel konsistent; TYPO3 website Sprache muss existieren, bevor Übersetzungen importiert werden.
6) Import in TYPO3
A) JSON → TYPO3 (kompaktes PHP, ausgerichtet auf Drupal JSON:API)
Beispiel Drupal JSON
{
"data": [{
"type": "node--article",
"id": "b5c1-uuid",
"attributes": {
"title": "Mein Artikel",
"body": { "value": "<p>HTML…</p>", "format": "basic_html" },
"created": "2025-05-01T10:20:30+00:00",
"langcode": "de",
"path": { "alias": "/blog/mein-artikel" }
},
"relationships": {
"field_image": { "data": [{ "type": "file--file", "id": "f-uuid" }] },
"field_tags": { "data": [{ "type": "taxonomy_term--tags", "id": "t-uuid" }] }
}
}],
"included": [{
"type": "file--file",
"id": "f-uuid",
"attributes": {
"filename": "hero.jpg",
"uri": { "url": "https://example.com/sites/default/files/hero.jpg" }
}
}]
} funktion fetchDocuments(string $url): array {
$out = [];
while ($url) {
$json = json_decode(file_get_contents($url), true);
if (!is_array($json)) break;
$out[] = $json;
$url = $json['links']['next']['href'] ?? null; // JSON:API Paginierung
}
return $out;
}
// Beispiel: Artikel mit Includes
$docs = fetchDocuments('https://drupal.example/jsonapi/node/article?filter[langcode]=en&include=field_image,uid,field_tags&page[limit]=50');
file_put_contents('stage/articles_en.json', json_encode($docs, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); $docs = json_decode(file_get_contents('stage/articles_en.json'), true);
function indexIncluded(array $doc): array {
$files = $terms = [];
foreach (($doc['included'] ?? []) as $res) {
if ($res['type'] === 'file--file') {
$files[$res['id']] = [
'uuid' => $res['id'],
'filename' => $res['attributes']['filename'] ?? '',
'url' => $res['attributes']['uri']['url'] ?? null,
];
} elseif (str_starts_with($res['type'], 'taxonomy_term--')) {
$terms[$res['id']] = [
'uuid' => $res['id'],
'name' => $res['attributes']['name'] ?? '',
'slug' => $res['attributes']['path']['alias'] ?? null
];
}
}
return [$files, $terms];
}
foreach ($docs as $doc) {
[$fileIndex, $termIndex] = indexIncluded($doc);
foreach ($termIndex as $t) {
upsertCategory($t['uuid'], ['title' => $t['name'], 'slug' => $t['slug'] ?: slugify($t['name'])]);
}
foreach ($doc['data'] as $node) {
if ($node['type'] !== 'node--article') continue;
$uuid = $node['id'];
$attr = $node['attributes'];
$rels = $node['relationships'] ?? [];
$title = $attr['title'] ?? '';
$body = $attr['body']['value'] ?? '';
$lang = $attr['langcode'] ?? 'en';
$alias = $attr['path']['alias'] ?? null;
$slug = $alias ?: '/'.slugify($title);
$pageUid = upsertPage($uuid, [
'pid' => 0,
'title' => $title,
'slug' => $slug,
'sys_language_uid' => langUid($lang),
]);
insertTextElement($pageUid, normalizeHtml($body), $title);
foreach ((array)($rels['field_image']['data'] ?? []) as $imgRef) {
$fileMeta = $fileIndex[$imgRef['id']] ?? null;
if (!$fileMeta || empty($fileMeta['url'])) continue;
$fileUid = ensureFalFromUrl($fileMeta['url'], $fileMeta['filename']);
attachImageToPage($pageUid, $fileUid);
}
foreach ((array)($rels['field_tags']['data'] ?? []) as $ref) {
relatePageToCategory($pageUid, externalIdToCategoryUid($ref['id']));
}
if ($alias) rememberRedirect($alias, $slug, 301);
}
}
flushRememberedRedirects();
/* Helper-Signaturen, die Sie mit TYPO3-APIs implementieren werden (DataHandler + FAL):
upsertCategory($externalId, $data): int
upsertPage($externalId, $data): int
insertTextElement($pid, $html, $header): int
ensureFalFromUrl($url, $filename): int
attachImageToPage($pageUid, $fileUid): void
relatePageToCategory($pageUid, $categoryUid): void
externalIdToCategoryUid($externalId): ?int
langUid($langcode): int
slugify($text): string
normalizeHtml($html): string
rememberRedirect($source, $target, $status): void
flushRememberedRedirects(): void
*/ Wenn Sie Drupal in CSVs exportieren können, die dem von T3Planet’s „Migrate WordPress to TYPO3“ verwendeten WordPress-Schema ähneln, können Sie dieses Tool auch für Drupal verwenden. Es ist ideal für Nicht-Entwickler-Teams und wiederholbare Trockenläufe.
Kartenfunktionen zu TYPO3 Extensions (praktisches Set)
| Drupal-Funktion | TYPO3 Extension | Schlüssel |
| Nachrichten/Blog | Nachrichtensystem | ext:news |
| SEO (Meta/Sitemap) | On-page SEO | ext:seo (Kern) |
| Formulare | Formular-Framework | ext:form |
| Newsletter | Direktmail / Integrationen | ext:direct_mail |
| eCommerce | Aimeos | ext:aimeos |
| Workflow | Arbeitsbereiche | Kern |
| Drush-ähnliche CLI | TYPO3-Konsole | Kern helhum/typo3-console |