Magento 2 · Declarative Schema

db_schema.xml
5 Fehler, die Entwickler vermeiden sollten

Declarative Schema ersetzt alte InstallScripts, aber nur wenn Tabellen, Constraints, Indexes und Patches sauber getrennt werden. Diese fünf Fehler verursachen die meisten Probleme in Magento-Projekten.

11 Min. Lesezeit Magento 2.4.8 Declarative Schema

1. Warum db_schema.xml wichtig ist

db_schema.xml Magento 2 ist der zentrale Mechanismus für deklaratives Datenbankschema. Statt Tabellen über alte Install- oder Upgrade-Scripts manuell zu erzeugen, beschreibst du den gewünschten Zielzustand der Datenbank in XML. Magento vergleicht diesen Zielzustand mit der aktuellen Datenbank und berechnet daraus die nötigen Änderungen. Das macht Schema-Änderungen nachvollziehbarer, reproduzierbarer und besser wartbar.

Der Vorteil ist groß, aber nur wenn die Datei sauber eingesetzt wird. db_schema.xml beschreibt Struktur: Tabellen, Spalten, Indexes und Constraints. Sie ist nicht für Datenmigration, Default-Datensätze, komplexe Umwandlungen oder Business-Logik gedacht. Genau an dieser Grenze entstehen viele Fehler. Entwickler schreiben zu viel in das Schema, vergessen Patches oder ändern bestehende Tabellen ohne klare Upgrade-Strategie.

Wer mit Magento 2.4.8 arbeitet, sollte deklaratives Schema als Standard verwenden. Neue Module brauchen keine InstallScripts mehr. Wenn ein Modul eigene Tabellen benötigt, gehört die Definition in app/code/Vendor/Module/etc/db_schema.xml. Datenänderungen gehören in Data Patches, komplexe Strukturmigrationen in Schema Patches oder bewusst geplante Upgrade-Schritte.

In Teams ist außerdem wichtig, dass Schema-Änderungen wie normaler Anwendungscode reviewed werden. Eine neue Spalte wirkt harmlos, kann aber Index-Größe, Importgeschwindigkeit, API-Antworten und Deployment-Zeit beeinflussen. Eine neue Foreign-Key-Beziehung kann Datenqualität verbessern, aber auch Löschprozesse blockieren. Eine zu breite Tabelle kann später Indexer und Exporte verlangsamen. Deshalb sollte jede Änderung an db_schema.xml Magento 2 mit der Frage beginnen, welche Datenmenge heute existiert und welche Datenmenge in zwölf Monaten realistisch ist.


<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="mironsoft_example" resource="default" engine="innodb" comment="Mironsoft Example">
        <column xsi:type="int" name="entity_id" unsigned="true" nullable="false" identity="true"
                comment="Entity ID"/>
        <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="created_at" nullable="false" default="CURRENT_TIMESTAMP"
                comment="Created At"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="entity_id"/>
        </constraint>
    </table>
</schema>

2. Fehler 1: InstallScripts weiterverwenden

Der erste Fehler ist der häufigste: Entwickler erstellen ein neues Modul und schreiben trotzdem InstallSchema oder UpgradeSchema. Das ist in modernen Magento-Projekten nicht mehr der richtige Weg. Wenn du eine neue Tabelle brauchst, gehört sie in db_schema.xml Magento 2. Alte Setup-Scripts machen Upgrades schwerer vorhersehbar und führen schneller zu unterschiedlichen Datenbankzuständen zwischen Entwicklung, Staging und Produktion.

Das bedeutet nicht, dass alte Module sofort komplett umgebaut werden müssen. Legacy-Code muss man kontrolliert migrieren. Für neue Module ist die Regel aber klar: kein InstallScript für Tabellenstruktur. Deklaratives Schema ist der Standard. Es beschreibt den Zielzustand, und Magento kümmert sich um die Differenz.

Ein praktischer Nebeneffekt: Neue Entwickler verstehen ein Modul schneller, wenn die Tabellenstruktur an einer festen Stelle liegt. Sie müssen nicht mehrere historische Upgrade-Scripts lesen und gedanklich ausführen, um den aktuellen Zustand zu rekonstruieren. Gerade bei langfristig gepflegten Magento-Shops spart das viel Zeit. Das Schema wird zur Dokumentation des aktuellen Datenmodells.


<?php
declare(strict_types=1);

namespace Mironsoft\Example\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;

/**
 * Deprecated approach for new Magento modules.
 */
class InstallSchema implements InstallSchemaInterface
{
    // Do not create new tables this way in new Magento 2 modules.
}

Die korrekte Variante ist eine saubere db_schema.xml. Dadurch sieht jeder Entwickler sofort, welche Tabellen und Spalten das Modul erwartet. Zusätzlich kann Magento Schema-Differenzen systematisch erkennen.

3. Fehler 2: Datenänderungen in db_schema.xml erzwingen

Der zweite Fehler ist subtiler: db_schema.xml wird für Dinge genutzt, die keine Struktur sind. Ein Beispiel ist das Einfügen von Konfigurationswerten, initialen Datensätzen oder komplexen Umwandlungen. Dafür ist db_schema.xml Magento 2 nicht gedacht. Sie beschreibt Tabellen und Spalten, nicht fachliche Daten.

Wenn dein Modul Default-Konfiguration braucht, nutzt du config.xml. Wenn es initiale Datensätze oder Migrationen braucht, nutzt du Data Patches. Wenn eine einmalige Strukturänderung nicht deklarativ sauber abbildbar ist, kommt ein Schema Patch infrage. Diese Trennung ist wichtig, weil Schema und Daten unterschiedliche Lebenszyklen haben.


<?php
declare(strict_types=1);

namespace Mironsoft\Example\Setup\Patch\Data;

use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

/**
 * Inserts initial example data for the module.
 */
final class AddInitialExampleData implements DataPatchInterface
{
    public function __construct(
        private readonly ModuleDataSetupInterface $moduleDataSetup
    ) {}

    public function apply(): self
    {
        $connection = $this->moduleDataSetup->getConnection();
        $connection->insertOnDuplicate(
            $this->moduleDataSetup->getTable('mironsoft_example'),
            [
                'entity_id' => 1,
                'title' => 'Initial Example'
            ],
            ['title']
        );

        return $this;
    }

    public static function getDependencies(): array
    {
        return [];
    }

    public function getAliases(): array
    {
        return [];
    }
}

4. Fehler 3: Constraints und Indexes unsauber definieren

Der dritte Fehler betrifft Constraints und Indexes. Viele Tabellen funktionieren zuerst auch ohne saubere Fremdschlüssel oder Indexes. Später entstehen dann Performance-Probleme oder Dateninkonsistenzen. Eine gute db_schema.xml Magento 2 definiert nicht nur Spalten, sondern auch Primärschlüssel, eindeutige Constraints, Foreign Keys und sinnvolle Indexes.

Besonders wichtig sind klare referenceId-Werte. Sie sollten stabil, lesbar und eindeutig sein. Wenn du sie ständig änderst, kann Magento unnötige Drop-and-Create-Operationen erkennen. Bei Foreign Keys muss außerdem das Löschverhalten bewusst gewählt werden. CASCADE ist nicht automatisch richtig. Manchmal ist SET NULL oder ein bewusstes Verhindern der Löschung fachlich sinnvoller.


<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="mironsoft_example_item" resource="default" engine="innodb" comment="Example Item">
        <column xsi:type="int" name="item_id" unsigned="true" nullable="false" identity="true"
                comment="Item ID"/>
        <column xsi:type="int" name="example_id" unsigned="true" nullable="false" comment="Example ID"/>
        <column xsi:type="varchar" name="sku" nullable="false" length="64" comment="SKU"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="item_id"/>
        </constraint>
        <constraint xsi:type="foreign" referenceId="MIRONSOFT_EXAMPLE_ITEM_EXAMPLE_ID"
                    table="mironsoft_example_item" column="example_id"
                    referenceTable="mironsoft_example" referenceColumn="entity_id"
                    onDelete="CASCADE"/>
        <constraint xsi:type="unique" referenceId="MIRONSOFT_EXAMPLE_ITEM_EXAMPLE_ID_SKU">
            <column name="example_id"/>
            <column name="sku"/>
        </constraint>
        <index referenceId="MIRONSOFT_EXAMPLE_ITEM_SKU" indexType="btree">
            <column name="sku"/>
        </index>
    </table>
</schema>

5. Fehler 4: Whitelist ignorieren

Der vierte Fehler ist die ignorierte db_schema_whitelist.json. Bei deklarativem Schema muss Magento wissen, welche Tabellen, Spalten und Constraints vom Modul verwaltet werden dürfen. Die Whitelist schützt vor versehentlichem Löschen von Datenbankstrukturen. Wenn sie fehlt oder veraltet ist, können Schema-Änderungen in bestimmten Situationen nicht sauber ausgeführt werden.

Gerade bei entfernten Spalten oder Constraints ist die Whitelist relevant. Entwickler testen lokal oft nur das Hinzufügen neuer Spalten. Das Entfernen oder Umbenennen kommt später und fällt erst in Staging oder Produktion auf. Deshalb sollte die Whitelist im Team nicht als Nebenprodukt betrachtet werden, sondern als Teil der Schema-Änderung.

In Pull Requests sollte die Whitelist deshalb bewusst mitbetrachtet werden. Wenn db_schema.xml geändert wurde, aber die Whitelist unverändert bleibt, ist das nicht automatisch falsch, aber es ist ein Prüfpunkt. Besonders bei Modulen, die in mehreren Shops installiert sind, kann eine veraltete Whitelist später zu schwer erklärbaren Upgrade-Unterschieden führen.


# Mark-Shust wrapper from the project root:
bin/magento setup:db-declaration:generate-whitelist --module-name=Mironsoft_Example

Die generierte Datei liegt im Modul unter etc/db_schema_whitelist.json. Sie sollte versioniert werden, wenn das Modul deklaratives Schema verwaltet. Bei jeder relevanten Schema-Änderung prüfst du, ob die Whitelist aktualisiert werden muss.

6. Fehler 5: Änderungen ohne Upgrade-Strategie

Der fünfte Fehler ist fehlende Planung. Eine Tabelle neu anzulegen ist einfach. Schwieriger wird es, wenn Spalten umbenannt, Typen geändert, Daten migriert oder Constraints verschärft werden. Eine Änderung in db_schema.xml Magento 2 kann auf einer leeren Entwicklungsdatenbank problemlos wirken und trotzdem in Produktion riskant sein.

Beispiel: Eine nullable Spalte wird plötzlich nullable="false". Lokal klappt das, weil kaum Daten existieren. In Produktion enthält die Spalte aber Null-Werte. Das Upgrade kann scheitern. Deshalb braucht jede relevante Schema-Änderung eine kleine Upgrade-Strategie: Welche Daten existieren? Muss ein Data Patch vorher Werte füllen? Ist die Änderung rückwärtskompatibel? Wie groß ist die Tabelle?


<?php
declare(strict_types=1);

namespace Mironsoft\Example\Setup\Patch\Data;

use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

/**
 * Backfills missing titles before the column becomes required.
 */
final class BackfillMissingTitles implements DataPatchInterface
{
    public function __construct(
        private readonly ModuleDataSetupInterface $moduleDataSetup
    ) {}

    public function apply(): self
    {
        $connection = $this->moduleDataSetup->getConnection();
        $table = $this->moduleDataSetup->getTable('mironsoft_example');

        $connection->update(
            $table,
            ['title' => 'Untitled'],
            'title IS NULL OR title = ""'
        );

        return $this;
    }

    public static function getDependencies(): array
    {
        return [];
    }

    public function getAliases(): array
    {
        return [];
    }
}

7. Vergleich: db_schema.xml vs. Patch

Der saubere Umgang mit db_schema.xml Magento 2 beginnt mit der richtigen Zuständigkeit. Nicht jede Datenbankänderung gehört in dieselbe Datei. Struktur gehört in deklaratives Schema. Daten gehören in Data Patches. Einmalige, komplexe Strukturabläufe können Schema Patches benötigen. Wer diese Grenze einhält, vermeidet viele Upgrade-Probleme.

Aufgabe Richtiger Ort Kommentar
Neue Tabelle db_schema.xml Deklarativer Zielzustand der Datenbank
Neue Spalte db_schema.xml Bei Pflichtspalten Datenbestand vorher prüfen
Initiale Datensätze Data Patch Nicht in Schema-Dateien verstecken
Datenmigration Data Patch Idempotent und bewusst planen
Komplexe Strukturmigration Schema Patch Nur wenn deklaratives Schema allein nicht reicht

Ein guter Prüfpunkt vor jedem Merge ist die Frage: „Beschreibt diese Änderung Struktur oder Daten?“ Wenn es Struktur ist, gehört sie meist in db_schema.xml. Wenn es Daten sind, gehört sie in einen Patch. Wenn es beides ist, müssen Reihenfolge und Abhängigkeit bewusst definiert werden.

Mironsoft

Magento 2 Datenbank, Module und Upgrade-Strategien

Schema-Änderungen ohne Upgrade-Risiko planen?

Wir entwickeln Magento 2 Module mit sauberem deklarativem Schema, Data Patches, klarer Upgrade-Reihenfolge und prüfbaren Datenbankänderungen für Staging und Produktion.

Schema Review

db_schema.xml, Constraints, Indexes und Whitelist prüfen

Patches

Data Patches und Schema Patches sauber abgrenzen

Deployment

Upgrade-Reihenfolge und Datenbestand vorab bewerten

9. Zusammenfassung

db_schema.xml Magento 2 ist der richtige Ort für deklarative Tabellenstruktur. Die häufigsten Fehler entstehen, wenn Entwickler alte InstallScripts weiterverwenden, Datenänderungen im Schema verstecken, Constraints vernachlässigen, die Whitelist ignorieren oder Änderungen ohne Upgrade-Strategie deployen.

Die robuste Regel ist einfach: Struktur in db_schema.xml, Daten in Data Patches, komplexe Sonderfälle bewusst planen. Jede Schema-Änderung sollte lokal, auf Staging und mit realistischem Datenbestand geprüft werden. So bleiben Magento-Upgrades berechenbar.

Für professionelle Magento-Module ist das kein Zusatzaufwand, sondern Risikoreduktion. Saubere Datenbankänderungen verhindern Deployment-Abbrüche, Inkonsistenzen und teure Nacharbeiten. Je größer der Shop und je mehr Integrationen auf dieselben Tabellen zugreifen, desto wichtiger wird diese Disziplin.

db_schema.xml Magento 2 — Das Wichtigste auf einen Blick

Struktur

Tabellen, Spalten, Constraints und Indexes gehören in db_schema.xml.

Daten

Initiale Datensätze und Migrationen gehören in Data Patches, nicht in Schema-Dateien.

Whitelist

db_schema_whitelist.json bei relevanten Schema-Änderungen prüfen und versionieren.

Upgrade

Pflichtspalten, Typänderungen und Drops immer mit realem Datenbestand bewerten.

10. FAQ: db_schema.xml in Magento 2

1 Was ist db_schema.xml in Magento 2?
Sie beschreibt das deklarative Datenbankschema eines Moduls: Tabellen, Spalten, Constraints und Indexes.
2 Soll man noch InstallSchema verwenden?
Für neue Module nein. Tabellenstruktur gehört in db_schema.xml, nicht in alte InstallScripts.
3 Gehören Datenänderungen in db_schema.xml?
Nein. Datenänderungen gehören in Data Patches. db_schema.xml beschreibt Struktur.
4 Wofür ist db_schema_whitelist.json?
Sie definiert verwaltete Schema-Elemente und schützt vor versehentlichen Drops. Bei relevanten Änderungen prüfen und versionieren.
5 Wie generiert man die Whitelist?
Mit dem Magento-Wrapper: bin/magento setup:db-declaration:generate-whitelist --module-name=Vendor_Module.
6 Wann braucht man einen Data Patch?
Wenn Daten eingefügt, migriert oder aufgefüllt werden müssen, zum Beispiel vor einer neuen Pflichtspalte.
7 Wann braucht man einen Schema Patch?
Für komplexe Strukturmigrationen, die nicht sauber über deklaratives Schema allein abbildbar sind.
8 Was ist bei nullable=false gefährlich?
Bestehende Null-Werte können das Upgrade blockieren. Vorher per Data Patch saubere Werte setzen.
9 Soll man Foreign Keys immer mit CASCADE löschen?
Nein. CASCADE nur nutzen, wenn Kinddaten fachlich automatisch gelöscht werden sollen.
10 Wie testet man Schema-Änderungen?
Auf leerer Datenbank und mit realistischem Datenbestand. Zusätzlich Whitelist, Constraints, Indexes und Datenmigrationen prüfen.