Doctrine migracje

Był już cykl o encjach, jeśli jeszcze go nie czytałeś, to polecam, warto nadrobić. Teraz gdy już masz zdefiniowaną strukturę bazy, to fajnie byłoby nią jakoś sensownie zarządzać. Do tego każdy programista doskonale wie, że schemat bazy jest bardzo dynamiczny, zmienia się nieustannie, więc bardzo ważne jest sensowne zarządzanie tymi zmianami. Dodatkowo, jeśli nad tym samym projektem pracuje kilka osób tym łatwiej o zmiany na bazie, które mogą się konfliktować albo problemy, jakie mogą powstać, gdy dwie osoby rozwijają ten sam fragment. W takich sytuacjach przychodzą z pomocą Doctrine migracje.

Czym są doctrine migracje?

Jest to rozszerzenie do Doctrina, które pozwala nam na sprawne zarządzanie schematem bazy, proste wdrażanie zmian oraz podnosi poziom bezpieczeństwa wdrożeń. A oto przykładowa migracja:

namespace Application\Migrations;
 
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
 
/**
 * Auto-generated Migration: Please modify to your needs!
 */
class Version20171207000000 extends AbstractMigration
{
    public function up(Schema $schema)
    {

    }

    public function down(Schema $schema)
    {

    }
}

Jak pewnie zauważyłeś, nazwa migracji jest schematyczna. Zaczyna się zawsze od Version, potem następuje data i czas jej wygenerowania. Bardzo rzadko, ale zdarza się, że wygenerują się dwie migracje z tym samym numerem. Wtedy trzeba po prostu ręcznie zmienić nazwę. Zdarzyło mi się, że ja i kolega wygenerowaliśmy migracje z tą samą nazwą. Dlatego mogę potwierdzić, że rzeczywiście jest to możliwe. Jednak da się z tego wybrnąć bez większych problemów, wszystko zależy od momentu wyłapania tego zgrzytu. Tutaj na pomoc przychodzi nam git, trzeba zwracać uwagę czy nie czyta naszej migracji jako modyfikacji innej.

Wszystkie migracje znajdziesz w katalogu app/DoctrineMigrations, każda zmiana na strukturze bazy pojawiająca się z czasem będzie nowym plikiem. Oprócz katalogu, w Twojej bazie danych pojawi się tabela przechowująca numery migracji wykonanych na tej bazie. Cała logika będzie opierać się na tej tabeli, wszystkie komendy konsolowe będą właśnie z niej brać informacje, które migracje nie zostały jeszcze wykonane, w jakiej kolejności były wykonywane itd.

Symfony

composer require doctrine/migrations

Instalacja DoctrineMigrationsBundle wygląda standardowo jak powyżej. Jeśli nie zrobi się to automatycznie, trzeba zarejestrować go w pliku AppKernel.php

 public function registerBundles()
 {
     $bundles = array(
         new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
     );
 }

Po tych dwóch krokach możemy używać wszelkich możliwych funkcji. Uruchomienie migracji w nowym projekcie, jest to banalnie proste. Trzeba jedynie pamiętać, aby zdefiniować schemat dla Encji, który możemy zrobić w formie adnotacji, plików yml lub xml.

// src/AppBundle/Entity/Event.php
 namespace AppBundle\Entity;

 use Doctrine\ORM\Mapping as ORM;

 /**
  * @ORM\Entity(repositoryClass="AppBundle\Repository\EventRepository")
  * @ORM\Table(name="events")
  */
 class Product
 {
     /**
      * @ORM\Column(type="integer")
      * @ORM\Id
      * @ORM\GeneratedValue(strategy="AUTO")
      */
     protected $id;

     /**
      * @ORM\Column(type="string", length=100, name="full_name")
      */
     protected $name;

     /**
      * @ORM\Column(type="decimal", scale=2)
      */
     protected $ticketPrice;

     /**
      * @ORM\Column(type="text")
      */
     protected $description;
 }

Oto przykład definiowania struktury w formie adnotacji. Zaczynamy od całej klasy, określamy ją jako encję, za jednym zamachem możemy zdefiniować również repozytorium. Kolejnym wpisem nazywamy tabelę. Następnie definiujemy kolumny i ich typ dla każdej zmiennej. Możemy określić już podstawową walidację np. length czy scale. Nazwę kolumny możemy zdefiniować parametrem name, tak jak jest to zrobione w przypadku parametru name w przykładzie. Jeśli nie określimy go, to będzie on taki sam jak nazwa zmiennej. W sytuacji dłuższych nazw, jak ticketPrice nazwa zostanie zrzutowana do małych liter i zamieniona z camelcase na undersocres, czyli ticket_price. Tak samo opisaną encję w formie pliku yml możecie zobaczyć poniżej:

# src/AppBundle/Resources/config/doctrine/Event.orm.yml
 AppBundle\Entity\Product:
     type: entity
     table: product
     id:
         id:
             type: integer
             generator: { strategy: AUTO }
     fields:
         name:
             type: string
             length: 100
         ticketPrice:
             type: decimal
             scale: 2
         description:
             type: text

Bardziej problematyczne jest wprowadzenie migracji do działającego już projektu. Zależy czy będziemy na jego podstawie stawiać kolejne instancje i po to chcemy wprowadzić migracje, aby w prosty sposób stawiać kolejne, czy po to, aby w łatwiejszy sposób zarządzać strukturą bazy w zespole osób pracujących nad tym samym projekcie.

Jeśli wdrażasz migracje do już działającego projektu, możesz wygenerować schemat w pierwszej migracji, bez danych startowych i potem pilnować jego rozwóju. Jednak przede wszystkich sprawdź, czy na pustym wygenerowanym schemacie nie wali 500, oczywiście nie mówię o błędach spowodowanych brakiem danych

Przydatne funkcje

Oto funkcje potrzebne do codziennego używania migracji:

generate –  generuje czystą, nową migracje.

migrate – wykonuje wszystkie migracje od ostatnio wykonanej na danej bazie danych.

version –  z parametrami –add oraz –delete możezmienić wartości w tabeli migracji

execute – wykonuje pojedyncza, wskazaną migrację

status – zwraca wszelkie przydatne informacje o aktualnym statusie migracji m.in. ostatnio wykonana, która zostanie wykonana w następnej kolejności, o ile taka jest zdefiniowana, podstawowe konfiguracje itp.

latest – zwraca nazwę ostatnio wykonanej migracji.

diff – generuje migracje zawierające wszystkie różnice między zdefiniowanym schematem a bazą danych.

Wywołujesz je jak akcje konsolowe np. bin/console doctrine:migrations:generate itp.

Miałeś do czynienia z migracjami? Daj znać w komentarzu! Jeśli to dla Ciebie nowość i masz dodatkowe pytania, napisz, pomogę.

Podobne posty

Jestem programistką, która lubi mieć ręce pełne roboty. Do życia potrzebuje komputera z internetem i kubka gorącej kawy. Więcej na stronie o mnie.

Comments

ZOSTAW ODPOWIEDŹ

Please enter your comment!
Please enter your name here