Magento 2: tworzenie tabeli za pomocą db_schema.xml

Od Magento 2.3 mamy dodatkowy sposób na dokonywanie operacji na tabeli w bazie danych. W tym wpisie omówię tworzenie tabeli za pomocą db_schema.xml w Magento 2. Dzięki odpowiedniej deklaracji w xml, nie potrzebujemy pisać kodu skryptów dla poszczególnych wersji, gdy chcemy choćby dodać nową/usunąć starą kolumnę w tabeli. Magento priorytezuje declarative schema i uruchamia je przed skryptami typu patch data i patch schema.

Korzystanie ze schematów bazy danych

Aby stworzyć nową tabelę dla naszego modułu, potrzebujemy:

  • Utworzyć plik db_schema.xml w katalogu etc modułu z odpowiednią definicją
  • Wygenerować plik db_schema_whitelist.json za pomocą:
  • Zastosować nowy schemat do bazy danych:
  • Ostatnim krokiem jest wyczyszczenie cache’a.

Baza danych do utworzenia

W notce o install, upgrade skryptach został przedstawiony przykład z księgą gości, gdzie została utworzona tabela guestbook. Tabela posiadała następujące kolumny:

  • entry_id
    • jako klucz główny,
    • typ int, liczba całkowita bez znaku (unsigned),
    • nie może być wartością pustą (null).
  • customer_id
    • jako klucz obcy,
    • może być null,
    • typu int, liczba całkowita bez znaku (unsigned),
    • nadajmy też tej kolumnie index.
  • user_name
    • maks 255 znaków,
    • jako string,
    • może być null.
  • subject
    • maks 255 znaków,
    • jako string,
    • nie może być null.
  • content
    • typu tekstowego,
    • nie może być null.
  • created_at
    • pole typu data z czasem,
    • nie może być null.
  • update_at
    • pole typu data z czasem,
    • nie może być null,
    • ustawiane podczas aktualizacji wpisu.

Stwórzmy do tego odpowiednią konfiguracje.

Przykładowy plik schema_db.xml

Do stworzenia tabeli guestbook i jej kolumny potrzebujemy utworzyć plik schema_db.xml w katalogu etc naszego modułu o następującej zawartości:

Powinniśmy mieć na uwadzę, że wszelkie operacje/modyfikacje w ramach deklaracji schematu możemy wykonywać tylko względem tabel/kolumn stworzonych w db_schema.xml. Jeśli chcemy na przykład usunąć kolumnę, to powinna ona być stworzona przez konfigurację w db_schema.xml. Przyjrzyjmy się bliżej dostępny opcjom tworzenia/manipulowania tabeli/kolumny.

Dostępne opcje konfiguracyjne w db_schema.xml

Magento 2 udostępnia nam łatwą możliwość stworzenia/modyfikacji tabeli/kolumny. Poniżej lista dostępnych elementów do ustawienia.

<table>

Węzeł <table> posiada takie atrybuty jak:

  • name — nazwa tabeli,
  • engine — jaki rodzaj silnika bazy danych. Dozwolone wartości to innodb lub memory,
  • resource — fragment bazy danych, na której ma być zainstalowana tabela. Dozwolone wartości to: ’default’, ’checkout’ lub ’sales’,
  • comment — komentarz do tabeli.
  • onCreate — jest to wyzwalacz (ang. trigger) DML, który umożliwia przeniesienie danych z istniejącej tabeli do nowo utworzonej tabeli. Ten rodzaj wyzwalacza działa tylko podczas tworzenia tabeli.

Wewnątrz węzła <table> mogą występować takie węzły jak:

  • <column> — konfiguracja dotycząca kolumny,
  • <constraint> — zależnie od typu możemy stworzyć klucze. Dostępne opcje to: primary, unique i foreign,
  • <index> — pozwala nam zdefiniować indeks. Dostępne typy to: btree, fulltext lub hash.

<column>

Węzeł <column> posiada następujące atrybuty:

  • xsi:type — określamy typ kolumny, który może być:
    • blob,
    • mediumblob,
    • longblob,
    • boolean,
    • date,
    • datetime,
    • decimal,
    • float,
    • int,
    • smallint,
    • bigint,
    • tinyint,
    • json,
    • real,
    • double,
    • text,
    • mediumtext,
    • longtext,
    • timestamp,
    • varbinary,
    • varchar.
  • default — pozwala na inicjalizację kolumny z określoną domyślną wartością.
  • disabled — wyłącza lub usuwa zadeklarowaną tablicę, kolumnę lub indeks,
  • identity — określenie, czy kolumna jest typu autoinrement czy nie,
  • length — określa ilość znaków w kolumnie. Może być użyta dla typów char, varchar lub varbinary,
  • nullable — określa czy dana kolumna może posiadać wartość pustą,
  • onCreate — jest to wyzwalacz (ang. trigger) DML, która umożliwia przeniesienie danych z istniejącej kolumny do tej nowo utworzonej. Ten rodzaj wyzwalacza działa tylko podczas tworzenia kolumny,
  • padding — określa rozmiar kolumny typów int, smallint, bigint, tinyint,
  • precision — liczba dozwolonych cyfr w typach real, decimal, float, double,
  • scale — liczba dozwolonych cyfr po przecinku w typach real, decimal, float, double,
  • unsigned — określamy, czy kolumna typu numerycznego, może zawierać wartości dodanie i ujemne, czy tylko wartości dodanie.

<contraint>

Węzeł <constraint> posiada następujące atrybuty:

  • type (wymagany) — typ ograniczenia, tutaj jedna z wartości: primary, unique lub foreign,
  • referenceId (wymagany) — niestandardowy identyfikator, który jest używany do mapowania relacji w zakresie plików db_schema.xml. Rzeczywista encja w bazie danych ma wygenerowaną nazwę.
  • Dla type określonego jako foreign wymagane jest zdefiniowanie poniższych atrybutów:
    • table — nazwa tabeli, dla której definiujemy klucz obcy,
    • column — nazwa kolumny w bieżącej tabeli, która odnosi się do określonej kolumny w innej tabeli,
    • referenceTable — nazwa tabeli, do której się odwołujemy,
    • referenceColumn — kolumna tabeli określonej w atrybucie referenceTable,
    • onDelete — wyzwalacz klucza obcego. Dozwolone wartości: CASCADE, SET NULL lub NO ACTION.
    • Dla ograniczenia schemat deklaratywny nie obsługuje wyzwalacza typu ON UPDATE, aby zachować wartości dla klucza jako niezmienne.
  • Dla type określonego jako index potrzebujemy określić atrybut:
    • indexType — wartość powinna być jedną z: btree, fulltext lub hash.

Skąd nazwa referenceId dla Indeksu?

W przykładzie mamy również referencję do indeksu:

Nazwa GUESTBOOK_CUSTOMER_ID_CUSTOMER_ENTITY_ID została utworzona przez konwencję
NAZWA_GŁÓWNEJ_TABELI_NAZWA_KLUCZA_OBCEGO_NAZWA_DRUGIEJ_TABELA_NAZWA_KLUCZA_GŁÓWNEGO. W zasadzie nie musimy sami budować nazwy indeksu, samo Magento nam to wygeneruje. Wystarczy wygenerować plik db_schema_whitelist.json, gdzie będzie informacja o nazwie wygenerowanej referencji. Nic nie stoi na przeszkodzie, aby ponownie potem wygenerować ten plik. Ostateczna wersja pliku db_schema_whitelist.json dla naszego przykładu wygląda następująco:

Dodanie kolumny visible

W przykładzie do tabeli guestbook powstał odpowiedni plik db_schema.xml. Brakuje w niej kolumny visible, która w oryginalnym kodzie została dodana przez skrypt typu upgrade.
Kolumna visible:

  • Typu boolean,
  • Nie może być pusta (null),
  • Ma domyślną wartość, która określa, aby jej nie pokazywać: 0.

Ponownie potrzebujemy wygenerować plik db_schema_whitelist.json za pomocą:

  • Zastosować zaktualizowany schemat do bazy danych:
  • Wyczyścić cache

Magento porówna różnice pomiędzy bazą a obecnym schematem i zastosuje odpowiednie zmiany.
Możemy zobaczyć, że wygenerowany na nowo plik db_schema_whitelist.json nie ma on informacji czy coś zostało dodane, zawiera po prostu dodatkową linijkę:

Powinniśmy mieć na uwadzę, że wszelkie operacje/modyfikacje w ramach deklaracji schematu możemy wykonywać tylko względem tabel/kolumn stworzonych w db_schema.xml. Jeśli chcemy na przykład usunąć kolumnę, to powinna ona być stworzona przez konfigurację w db_schema.xml.

Automatyczna konwersja starych skryptów do db_schema.xml

W przestawionym przykładzie pokazano, w jaki sposób przejść ze starego skryptu do użytkowania db_schema.xml. Istnieje również opcja, aby zrobić to automatycznie.

Nie jest to całkiem bezproblematyczne, ponieważ wiąże się to z usunięciem wpisu modułu z tabeli setup_module. Trzeba zadbać o to, żeby była wykonana kopia danych.