Zum Inhalt springen
Abstrakte Formen aus Mattglas: ein gefaltetes Blatt wird zu einer neuen, klareren Form umgefaltet

ACF-Felder nach Statamic übertragen: Content-Mapping in der Praxis

Wer ACF-Felder nach Statamic übertragen will, modelliert zuerst: Beitragstypen werden zu Collections, Feldgruppen zu Blueprints, Doppeltes wird zusammengelegt. Erst dann holt ein wiederholbares Skript die Inhalte aus WordPress.

9 min Lesezeit Statamic

Eine WordPress-Website mit Advanced Custom Fields (ACF) ist meist über Jahre gewachsen. Neue Anforderungen bekamen ein neues Feld, manchmal einen neuen Beitragstyp, selten wurde etwas entfernt. Wer diesen Bestand eins zu eins nach Statamic kopiert, nimmt die Unordnung mit. Wer zuerst ein sauberes Modell entwirft, bekommt ein System, in dem die Redaktion schneller findet, was sie pflegen muss.

Das Content-Mapping ist deshalb der wichtigste Teil jeder Migration, und es kommt vor dem ersten Import. Ob Statamic für Ihre Website überhaupt die bessere Wahl ist, klärt der Vergleich Statamic oder WordPress.

Inventur

Was in WordPress steckt

Die Bestandsaufnahme erfasst drei Dinge: Beitragstypen, Taxonomien und ACF-Feldgruppen. Beitragstypen sind die Inhaltsarten, die WordPress neben Seiten und Beiträgen kennt, etwa Referenzen, Stellen oder Produkte. Taxonomien sind die Ordnungssysteme dazu, also Kategorien, Schlagwörter oder eigene wie Branche und Standort. ACF-Feldgruppen legen fest, welche zusätzlichen Felder ein Beitragstyp hat.

Die Definitionen der Feldgruppen liegen in der Datenbank oder, wenn die Funktion Local JSON aktiv ist, als JSON-Dateien im Ordner acf-json des Themes. Die Dateien sind die bequemste Quelle, weil sie Feldtyp, Name und Einstellungen jedes Felds enthalten.

Die Definitionen zeigen, was es geben könnte. Was tatsächlich gepflegt wird, zeigt die Tabelle wp_postmeta, in der WordPress die Feldwerte speichert. Eine Abfrage zählt, wie oft jedes Feld einen Wert hat:

Abfrage auf einer Kopie der WordPress-Datenbank sql
SELECT pm.meta_key, p.post_type, COUNT(*) AS gefuellt
FROM wp_postmeta pm
JOIN wp_posts p ON p.ID = pm.post_id
WHERE pm.meta_key NOT LIKE '!_%' ESCAPE '!'  -- Felder ohne führenden Unterstrich
  AND pm.meta_value <> ''
  AND p.post_status = 'publish'
GROUP BY pm.meta_key, p.post_type
ORDER BY p.post_type, gefuellt DESC;

Auswertung

Was die Zählung verrät

Das Ergebnis dieser Abfrage ist oft die nützlichste Seite der ganzen Inventur. Felder, die bei 400 Referenzen dreimal gefüllt sind, sind Kandidaten zum Streichen oder zum Zusammenlegen mit einem anderen Feld. Einträge mit Ziffern im Namen, etwa ansprechpartner_0_name und ansprechpartner_1_name, gehören zu einem Repeater: ACF speichert jede Zeile und jedes Unterfeld als eigenen Eintrag nach dem Muster Feldname, Zeilennummer, Unterfeld. Einträge mit führendem Unterstrich verweisen auf die Felddefinition und werden nicht migriert, deshalb filtert die Abfrage sie heraus. Der Unterstrich ist in LIKE selbst ein Platzhalter für ein beliebiges Zeichen und muss maskiert werden. Die Abfrage nutzt dafür ESCAPE mit einem eigenen Zeichen, weil der übliche Backslash nicht wirkt, wenn der MySQL-Server im SQL-Modus NO_BACKSLASH_ESCAPES läuft.

Für die Planung zählt auch, was nicht in wp_postmeta steht: Inhalte, die Plugins in eigenen Tabellen speichern, etwa Formulare, Übersetzungen oder Shop-Daten. Sie brauchen eine eigene Zeile im Mapping.

Taxonomien, Sprachen und Autoren

Taxonomien lassen sich meist direkt übernehmen. In Statamic sind sie eigene Taxonomien mit Begriffen, die Einträge verweisen über ein Feld vom Typ terms darauf. Auch hier hilft der Blick auf die Zahlen: Schlagwörter, die nur einem einzigen Beitrag zugeordnet sind, machen die Navigation unübersichtlich und können vor dem Umzug zusammengefasst werden.

Mehrsprachige WordPress-Websites nutzen meist ein Plugin wie WPML oder Polylang, die Übersetzungen als eigene Beiträge mit einer Verknüpfung speichern. In Statamic hängt eine Übersetzung als Lokalisierung am Originaleintrag einer anderen Site. Das Skript muss die Verknüpfung aus dem Plugin lesen und die Übersetzung dem richtigen Original zuordnen. Wie Statamic mehrere Sites und Sprachen organisiert, steht unter Statamic 6 Multi-Site-Setup.

Autoren sind in WordPress Benutzerkonten. Wer im Frontend nur Name und Foto braucht, legt in Statamic eine kleine Collection für Autoren an, statt jedem ehemaligen Redakteur ein Konto im Control Panel zu geben.

Viele kleine helle Blätter liegen verstreut und laufen in drei saubere Stapel zusammen, einer davon ist orange.

Modell

Zusammenlegen statt eins zu eins kopieren

Das neue Modell entsteht aus der Frage, was die Redaktion pflegt; was WordPress gespeichert hat, ist nur der Ausgangspunkt. In Statamic werden Inhaltsarten zu Collections, ihre Felder stehen im Blueprint, wiederkehrende Feldgruppen in Fieldsets, die mehrere Blueprints einbinden.

Drei Muster tauchen bei gewachsenen WordPress-Websites häufig auf:

  • Mehrere Beitragstypen für dieselbe Sache. News, Pressemitteilungen und Veranstaltungsrückblicke haben fast dieselben Felder. In Statamic wird daraus eine Collection mit einer Taxonomie für die Art.

  • Dieselben Felder in vielen Feldgruppen. Ansprechpartner, Teaserbild und SEO-Angaben sind in jeder Feldgruppe neu angelegt. In Statamic stehen sie einmal in einem Fieldset.

  • Seiten mit Flexible Content. Der ACF-Feldtyp für frei kombinierbare Abschnitte wird in Statamic zum Replicator mit Sets oder zu Bard mit Sets, wenn Fließtext und Bausteine sich abwechseln.

Die Trennung zwischen festen Daten und redaktionellem Text ist keine neue Frage. Für ein Online-Portal, eines unserer frühen Festpreisprojekte (Case Study von 2012), lagen die strukturierten Stammdaten und Listings in TYPO3 und der redaktionelle Bereich in WordPress, unter einem gemeinsamen Frontend. Laut Case Study würde man das heute wahrscheinlich mit einem einzigen Content-Hub lösen. In Statamic ist das der Normalfall: Stammdaten als Collection mit festen Feldern, Fließtext in Bard, beides in einer Installation.

Für die einzelnen Felder hilft eine Zuordnung der Feldtypen. Die Statamic-Namen entsprechen den Feldtypen in Statamic 6:

  • Text, Textbereich, Zahl, E-Mail und URL: text, textarea, integer oder float, text mit Validierung

  • WYSIWYG-Editor: bard, bei Bedarf markdown

  • Bild, Datei und Galerie: assets, bei Einzelbildern mit max_files 1

  • Beziehung und Beitragsobjekt: entries

  • Taxonomie: terms

  • Wahr/Falsch: toggle

  • Auswahl, Radio-Button, Checkbox: select, radio, checkboxes

  • Datumsauswahl: date

  • Link: link

  • Gruppe: group

  • Repeater: grid, oder replicator, wenn die Zeilen unterschiedlich aufgebaut sind

  • Flexible Content: replicator oder bard mit Sets

Ein Ausschnitt aus einem Blueprint zeigt, wie das Ergebnis aussieht. Das Feld wp_id ist versteckt und hält die alte WordPress-ID fest, damit das Skript später jeden Eintrag wiederfindet:

resources/blueprints/collections/referenzen/referenz.yaml (Ausschnitt) yaml
title: Referenz
tabs:
  main:
    sections:
      -
        fields:
          -
            handle: title
            field:
              type: text
              required: true
          -
            handle: kunde
            field:
              type: text
          -
            handle: branchen
            field:
              type: terms
              taxonomies:
                - branchen
          -
            handle: bilder
            field:
              type: assets
              container: assets
              folder: referenzen
          -
            handle: ansprechpartner
            field:
              type: grid
              fields:
                -
                  handle: name
                  field:
                    type: text
                -
                  handle: telefon
                  field:
                    type: text
          -
            handle: wp_id
            field:
              type: hidden

Medien

Bilder, Dateien und Shortcodes

Medien und Platzhalter im Text machen bei der Migration die meiste Handarbeit. Drei Stellen verlangen Aufmerksamkeit.

Bilder in Feldern. ACF speichert für Bild- und Dateifelder meist die ID des Anhangs. Das Skript schlägt die ID in WordPress nach, lädt die Originaldatei und legt sie im passenden Ordner des Statamic-Asset-Containers ab.

Bilder im Fließtext. Im Text stehen Bilder als HTML mit Adressen wie /wp-content/uploads/2021/03/halle-300x200.jpg. Die Endung -300x200 verweist auf eine von WordPress erzeugte Verkleinerung, nicht auf das Original. Wer diese Dateien übernimmt, hat in Statamic unscharfe Bilder. Das Skript entfernt die Größenangabe, sucht das Original und lässt Statamic die Größen selbst erzeugen.

Shortcodes und Blöcke. Shortcodes sind Platzhalter in eckigen Klammern, etwa für Galerien oder Formulare von Plugins. Statamic kennt sie nicht. Jeder Shortcode-Typ wird einmal entschieden: als Set in Bard nachbauen, durch einen Link ersetzen oder entfernen. Inhalte aus dem Block-Editor Gutenberg speichert WordPress als HTML mit Kommentaren wie wp:paragraph, in denen die Einstellungen des Blocks stehen. Standardblöcke lassen sich zuordnen, Blöcke aus Plugins brauchen eigene Regeln.

Welche Shortcodes vorkommen, zeigt eine Suche in wp_posts nach dem Muster eckige Klammer plus Name. Die Liste ist meist kürzer als befürchtet, und jeder Eintrag darauf ist eine Entscheidung, keine Programmierarbeit.

Zwischen zwei Platten läuft ein orange gestrichelter Kreislauf hin und zurück, ein wiederholbarer Lauf.

Skript

Das Migrationsskript wiederholbar bauen

Ein Migrationsskript läuft viele Male: gegen eine Kopie der Daten, nach jeder Korrektur am Mapping und am Ende noch einmal am Tag des Umzugs. Deshalb muss es idempotent sein, also bei jedem Lauf zum selben Ergebnis kommen, ohne Einträge doppelt anzulegen.

Wie viele Durchläufe nötig sind, zeigt sich erst am Bestand. In unserem Migrations-Sprint sind in der dritten Woche zwei vollständige Probemigrationen gegen eine Kopie der Produktivdaten eingeplant, jeweils mit gemeinsamer Durchsicht der Ergebnisse. Erst danach folgt der letzte Lauf zum Livegang. Jede Korrektur, die zwischen den Läufen ins Mapping wandert, kommt beim nächsten Lauf automatisch bei allen Einträgen an.

Für Bestände ohne verschachtelte Felder gibt es das offizielle Addon Statamic Importer, seit dem 28.01.2026 in Version 2 für Statamic 6. Es importiert Einträge, Begriffe und Benutzer aus CSV- oder XML-Dateien. Laut Dokumentation enthält der Standardexport von WordPress ACF-Felder nicht in sauberer Form, empfohlen wird ein CSV-Export über ein Plugin wie WP All Export. Felder vom Typ Replicator lassen sich im Importer nicht direkt zuordnen. Wer viel Flexible Content hat, landet deshalb oft beim eigenen Skript.

Das eigene Skript ist in Laravel und Statamic ein Artisan-Befehl mit drei Eigenschaften:

  1. Er findet bestehende Einträge über die alte WordPress-ID und aktualisiert sie, statt neue anzulegen.

  2. Er hat einen Probemodus, der nur protokolliert, was er tun würde.

  3. Er schreibt ein Protokoll mit jedem übersprungenen Feld und jedem nicht gefundenen Bild.

Der Kern sieht so aus. Der Ausschnitt steht in der handle-Methode des Befehls, der Probemodus ist als Option --dry-run in der Signatur angelegt:

app/Console/Commands/ImportReferenzen.php (Ausschnitt) php
use Statamic\Facades\Entry;

$entry = Entry::query()
    ->where('collection', 'referenzen')
    ->where('wp_id', $post->ID)
    ->first()
    ?? Entry::make()->collection('referenzen');

$entry->slug($post->post_name)
    ->published($post->post_status === 'publish')
    ->data([
        'title'           => $post->post_title,
        'wp_id'           => $post->ID,
        'kunde'           => $meta['kunde'] ?? null,
        'branchen'        => $this->branchen($post),
        'ansprechpartner' => $this->repeater($meta, 'ansprechpartner', ['name', 'telefon']),
    ]);

if ($this->option('dry-run')) {
    $this->line("Würde speichern: {$post->post_name}");
} else {
    $entry->save();
}

Vor und nach dem Livegang

Wann data() und wann merge()

data([...]) ersetzt bei jedem Lauf alle Felder des Eintrags durch die Werte aus WordPress. Vor dem Livegang ist das gewollt: Jede Korrektur am Mapping wirkt überall, und nichts Altes bleibt hängen. Nach dem Livegang würde derselbe Lauf aber alles überschreiben, was die Redaktion inzwischen im Control Panel geändert hat. Muss das Skript dann noch einmal laufen, etwa für nachgelieferte Einträge, setzt es nur noch die Felder, die es wirklich übernehmen soll, mit merge([...]), oder es überspringt Einträge, die es schon gibt.

Abnahme

Stichproben und Abnahme

Die Abnahme prüft Zahlen, Stichproben und Adressen. Zuerst die Zahlen: Anzahl veröffentlichter Einträge je Beitragstyp in WordPress gegen die Anzahl je Collection in Statamic. Jede Abweichung muss das Protokoll erklären.

Dann die Stichproben:

  • je Collection zehn zufällige Einträge, Feld für Feld gegen das Original,

  • die Seiten mit den meisten Aufrufen laut Statistik oder Google Search Console vollständig,

  • jeder Eintrag mit Repeater oder Flexible Content mindestens einmal je Aufbau,

  • Bilder in voller Größe, Dateien zum Herunterladen, interne Links.

Zuletzt die Adressen. Jede alte URL braucht ein Ziel, sonst gehen Links und Rankings verloren. Weil das Skript die alte ID und den alten Slug kennt, kann es die Liste der Weiterleitungen gleich mit erzeugen.

Bevor die neue Website live geht, läuft sie auf einer Staging-Umgebung, dort prüft die Redaktion mit echten Inhalten.

Ihr Content-Mapping in einer Woche

Wir inventarisieren Ihre WordPress-Website, entwerfen Collections und Blueprints und bauen das Skript, mit dem Ihre Inhalte sauber in Statamic landen.

Zum Statamic-Migration-Sprint

Kurz beantwortet

Häufige Fragen

  • Standardblöcke wie Absatz, Überschrift, Liste, Bild, Tabelle oder Zitat lassen sich zuordnen, der offizielle Statamic Importer legt dafür passende Sets in Bard an. Blöcke aus Plugins oder eigene Blöcke brauchen eine eigene Regel im Import. Wie viele davon vorkommen, zeigt eine Suche nach den Block-Kommentaren in der Datenbank.

  • Statamic kennt keine Shortcodes, sie würden als Text in eckigen Klammern erscheinen. Jeder Shortcode-Typ wird deshalb einmal entschieden: als Baustein nachbauen, durch einen Link ersetzen oder entfernen. Das Skript setzt die Entscheidung dann für alle Vorkommen um.

  • In WordPress schon, wenn das Skript wiederholbar ist. Es läuft während des Projekts gegen Kopien und am Umzugstag ein letztes Mal gegen den aktuellen Stand. Nur für diesen letzten Lauf und die Prüfung danach braucht es eine kurze Pause in der Redaktion.

Nachweise

Quellen und Stand

Stand: 06.08.2026. Feldtypen laut Statamic-6-Dokumentation, Importer laut Dokumentation und Versionsliste auf Packagist, ACF-Speicherung laut ACF-Dokumentation, Blockformat laut WordPress-Entwicklerdokumentation, LIKE und ESCAPE laut MySQL-Referenzhandbuch, Angaben zum Online-Portal laut Case Study.