W czasie rozwoju i utrzymywania aplikacji zasilanej danymi z bazy danych, struktura tej ostatniej ewoluuje podobnie jak sam kod źródłowy. Przykładowo, rozbudowując aplikację konieczne jest dodanie nowej tabeli, lub też już po wydaniu aplikacji na serwerze produkcyjnym przydałby się indeks, aby poprawić wydajność zapytania itd. Zmiana struktury bazy danych często pociąga za sobą zmiany w kodzie źródłowym, dlatego też Yii udostępnia funkcjonalność tak zwanych migracji bazodanowych, która pozwala na kontrolowanie zmian w bazie danych (migracji).
Poniższe kroki pokazują, jak migracje mogą być wykorzystane przez zespół deweloperski w czasie pracy:
A poniższe kroki opisują w skrócie jak stworzyć nowe wydanie z migracją bazy danych na produkcji:
Yii udostępnia zestaw narzędzi konsolowych, które pozwalają na:
Powyższe narzędzia są dostępne poprzez komendę yii migrate
. W tej sekcji opiszemy szczegółowo w jaki sposób z nich
korzystać. Możesz również zapoznać się ze sposobem użycia narzędzi w konsoli za pomocą komendy pomocy yii help migrate
.
Wskazówka: Migracje mogą modyfikować nie tylko schemat bazy danych, ale również same dane, a także mogą służyć do innych zadań jak tworzenie hierarchi kontroli dostępu dla ról (RBAC) lub czyszczenie pamięci podręcznej.
Uwaga: Modyfikowanie danych w migracji zwykle jest znacznie prostsze, jeśli użyje się do tego klas Active Record, dzięki logice już tam zaimplementowanej. Należy jednak pamiętać, że logika aplikacji jest podatna na częste zmiany, a naturalnym stanem kodu migracji jest jego stałość - w przypadku zmian w warstwie Active Record aplikacji ryzykujemy zepsucie migracji, które z niej korzystają. Z tego powodu kod migracji powinien być utrzymywany niezależnie od pozostałej logiki aplikacji.
Aby utworzyć nową migrację, uruchom poniższą komendę:
yii migrate/create <nazwa>
Wymagany argument nazwa
przekazuje zwięzły opis migracji. Przykładowo, jeśli migracja ma dotyczyć utworzenia nowej
tabeli o nazwie news, możesz użyć jako argumentu create_news_table
i uruchomić komendę:
yii migrate/create create_news_table
Uwaga: Argument
nazwa
zostanie użyty jako część nazwy klasy nowej migracji i z tego powodu powinien składać się tylko z łacińskich liter, cyfr i/lub znaków podkreślenia.
Powyższa komenda utworzy nowy plik klasy PHP o nazwie podobnej do m150101_185401_create_news_table.php
w folderze
@app/migrations
. Plik będzie zawierał poniższy kod, gdzie zadeklarowany jest szkielet klasy m150101_185401_create_news_table
:
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration
{
public function up()
{
}
public function down()
{
echo "m101129_185401_create_news_table cannot be reverted.\n";
return false;
}
/*
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}
Każda migracja zdefiniowana jest jako klasa PHP rozszerzająca yii\db\Migration. Nazwa klasy migracji jest generowana
automatycznie w formacie m<YYMMDD_HHMMSS>_<Nazwa>
, gdzie
<YYMMDD_HHMMSS>
to data i czas UTC wskazujące na moment utworzenia migracji,<Nazwa>
jest identyczna z wartością argumentu nazwa
podanego dla komendy.Wewnątrz klasy migracji należy napisać kod w metodzie up()
, która wprowadzi zmiany w strukturze bazy danych.
Można również napisać kod w metodzie down()
, który spowoduje cofnięcie zmian wprowadzonych w up()
. Metoda up()
jest
uruchamiana w momencie aktualizacji bazy, a down()
w momencie przywracania jej do poprzedniego stanu.
Poniższy kod pokazuje, jak można zaimplementować klasę migracji, aby utworzyć tabelę news
:
<?php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration
{
public function up()
{
$this->createTable('news', [
'id' => Schema::TYPE_PK,
'title' => Schema::TYPE_STRING . ' NOT NULL',
'content' => Schema::TYPE_TEXT,
]);
}
public function down()
{
$this->dropTable('news');
}
}
Informacja: Nie wszystkie migracje są odwracalne. Dla przykładu, jeśli w
up()
usuwane są wiersze z tabeli, możesz nie być w stanie przywrócić ich w metodziedown()
. Może też zdarzyć się, że celowo nie podasz nic wdown()
- cofanie zmian migracji bazy danych nie jest czymś powszechnym - w takim wypadku należy zwrócićfalse
w metodziedown()
, aby wyraźnie wskazać, że migracja nie jest odwracalna.
Podstawowa klasa migracji yii\db\Migration umożliwia połączenie z bazą danych poprzez właściwość db. Możesz użyć jej do modyfikowania schematu bazy za pomocą metod opisanych w sekcji Praca ze schematem bazy danych.
Przy tworzeniu tabeli albo kolumny zamiast używać rzeczywistych typów, powinno się stosować typy abstrakcyjne, dzięki
czemu migracje będą niezależne od pojedynczych silników bazodanowych. Klasa yii\db\Schema definiuje zestaw stałych,
które reprezentują wspierane typy abstrakcyjne. Stałe te nazwane są według schematu TYPE_<Nazwa>
. Dla przykładu,
TYPE_PK
odnosi się do typu klucza głównego z autoinkrementacją; TYPE_STRING
do typu łańcucha znaków. Kiedy migracja
jest dodawana do konkretnej bazy danych, typy abstrakcyjne są tłumaczone na odpowiadające im typy rzeczywiste. W przypadku
MySQL, TYPE_PK
jest zamieniony w int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
, a TYPE_STRING
staje się varchar(255)
.
Możesz łączyć abstrakcyjne typy z dodatkowymi definicjami - w powyższym przykładzie NOT NULL
jest dodane do
Schema::TYPE_STRING
, aby oznaczyć, że kolumna nie może być ustawiona jako null
.
Informacja: Mapowanie typów abstrakcyjnych na rzeczywiste jest określone we właściwości $typeMap dla każdej klasy
QueryBuilder
poszczególnych wspieranych silników baz danych.
Począwszy od wersji 2.0.6, możesz skorzystać z nowej klasy budowania schematów, która pozwala na znacznie wygodniejszy sposób definiowana kolumn. Dzięki temu migracja z przykładu powyżej może być napisana następująco:
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration
{
public function up()
{
$this->createTable('news', [
'id' => $this->primaryKey(),
'title' => $this->string()->notNull(),
'content' => $this->text(),
]);
}
public function down()
{
$this->dropTable('news');
}
}
Lista wszystkich metod do definiowania typów kolumn dostępna jest w dokumentacji API dla yii\db\SchemaBuilderTrait.
Począwszy od wersji 2.0.7 konsola migracji pozwala na wygodne utworzenie nowej migracji.
Jeśli nazwa migracji podana jest w jednej z rozpoznawalnych form, np. create_xxx_table
lub drop_xxx_table
, wtedy
wygenerowany plik migracji będzie zawierał dodatkowy kod, w tym przypadku odpowiednio kod tworzenia i usuwania tabeli.
Poniżej opisane są wszystkie warianty tej funkcjonalności.
yii migrate/create create_post_table
generuje
/**
* Handles the creation for table `post`.
*/
class m150811_220037_create_post_table extends Migration
{
/**
* {@inheritdoc}
*/
public function up()
{
$this->createTable('post', [
'id' => $this->primaryKey()
]);
}
/**
* {@inheritdoc}
*/
public function down()
{
$this->dropTable('post');
}
}
Aby jednocześnie od razu dodać kolumny tabeli, zdefiniuj je za pomocą opcji --fields
.
yii migrate/create create_post_table --fields="title:string,body:text"
generuje
/**
* Handles the creation for table `post`.
*/
class m150811_220037_create_post_table extends Migration
{
/**
* {@inheritdoc}
*/
public function up()
{
$this->createTable('post', [
'id' => $this->primaryKey(),
'title' => $this->string(),
'body' => $this->text(),
]);
}
/**
* {@inheritdoc}
*/
public function down()
{
$this->dropTable('post');
}
}
Możesz określić też więcej parametrów kolumny.
yii migrate/create create_post_table --fields="title:string(12):notNull:unique,body:text"
generuje
/**
* Handles the creation for table `post`.
*/
class m150811_220037_create_post_table extends Migration
{
/**
* {@inheritdoc}
*/
public function up()
{
$this->createTable('post', [
'id' => $this->primaryKey(),
'title' => $this->string(12)->notNull()->unique(),
'body' => $this->text()
]);
}
/**
* {@inheritdoc}
*/
public function down()
{
$this->dropTable('post');
}
}
Uwaga: Klucz główny jest dodawany automatycznie i nazwany domyślnie
id
. Jeśli chcesz użyć innej nazwy, możesz zdefiniować go bezpośrednio np.--fields="name:primaryKey"
.
Począwszy od wersji 2.0.8 generator pozwala na zdefiniowanie kluczy obcych za pomocą opcji foreignKey
.
yii migrate/create create_post_table --fields="author_id:integer:notNull:foreignKey(user),category_id:integer:defaultValue(1):foreignKey,title:string,body:text"
generuje
/**
* Handles the creation for table `post`.
* Has foreign keys to the tables:
*
* - `user`
* - `category`
*/
class m160328_040430_create_post_table extends Migration
{
/**
* {@inheritdoc}
*/
public function up()
{
$this->createTable('post', [
'id' => $this->primaryKey(),
'author_id' => $this->integer()->notNull(),
'category_id' => $this->integer()->defaultValue(1),
'title' => $this->string(),
'body' => $this->text(),
]);
// creates index for column `author_id`
$this->createIndex(
'idx-post-author_id',
'post',
'author_id'
);
// add foreign key for table `user`
$this->addForeignKey(
'fk-post-author_id',
'post',
'author_id',
'user',
'id',
'CASCADE'
);
// creates index for column `category_id`
$this->createIndex(
'idx-post-category_id',
'post',
'category_id'
);
// add foreign key for table `category`
$this->addForeignKey(
'fk-post-category_id',
'post',
'category_id',
'category',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function down()
{
// drops foreign key for table `user`
$this->dropForeignKey(
'fk-post-author_id',
'post'
);
// drops index for column `author_id`
$this->dropIndex(
'idx-post-author_id',
'post'
);
// drops foreign key for table `category`
$this->dropForeignKey(
'fk-post-category_id',
'post'
);
// drops index for column `category_id`
$this->dropIndex(
'idx-post-category_id',
'post'
);
$this->dropTable('post');
}
}
Umiejscowienie słowa foreignKey
w definicji kolumny nie ma znaczenia dla generatora, zatem:
author_id:integer:notNull:foreignKey(user)
author_id:integer:foreignKey(user):notNull
author_id:foreignKey(user):integer:notNull
wygenerują ten sam kod.
Opcja foreignKey
może być wzbogacona o parametr w nawiasach, który oznacza nazwę tabeli relacji dla generowanego
klucza obcego. Bez tego parametru użyta zostanie nazwa tabeli relacji zgodna z nazwą kolumny.
W przykładzie powyżej author_id:integer:notNull:foreignKey(user)
wygeneruje kolumnę o nazwie author_id
z kluczem
obcym wskazującym na tabelę user
, natomiast category_id:integer:defaultValue(1):foreignKey
wygeneruje kolumnę
category_id
z kluczem obcym wskazującym na tabelę category
.
Począwszy od wersji 2.0.11, dla foreignKey
można podać drugi parametr, oddzielony białym znakiem, z nazwą kolumny
relacji dla generowanego klucza obcego. Jeśli drugi parametr nie jest podany, nazwa kolumny jest pobierana ze schematu tabeli.
Jeśli schemat nie istnieje , klucz główny nie jest ustawiony lub jest kluczem kompozytowym, używana jest domyślna nazwa id
.
yii migrate/create drop_post_table --fields="title:string(12):notNull:unique,body:text"
generuje
class m150811_220037_drop_post_table extends Migration
{
public function up()
{
$this->dropTable('post');
}
public function down()
{
$this->createTable('post', [
'id' => $this->primaryKey(),
'title' => $this->string(12)->notNull()->unique(),
'body' => $this->text()
]);
}
}
Jeśli nazwa migracji jest w postaci add_xxx_column_to_yyy_table
, wtedy plik będzie zawierał wywołania metod addColumn
i dropColumn
.
Aby dodać kolumnę:
yii migrate/create add_position_column_to_post_table --fields="position:integer"
co generuje
class m150811_220037_add_position_column_to_post_table extends Migration
{
public function up()
{
$this->addColumn('post', 'position', $this->integer());
}
public function down()
{
$this->dropColumn('post', 'position');
}
}
Możesz dodać wiele kolumn jednocześnie:
yii migrate/create add_xxx_column_yyy_column_to_zzz_table --fields="xxx:integer,yyy:text"
Jeśli nazwa migracji jest w postaci drop_xxx_column_from_yyy_table
, wtedy plik będzie zawierał wywołania metod
dropColumn
i addColumn
.
yii migrate/create drop_position_column_from_post_table --fields="position:integer"
generuje
class m150811_220037_drop_position_column_from_post_table extends Migration
{
public function up()
{
$this->dropColumn('post', 'position');
}
public function down()
{
$this->addColumn('post', 'position', $this->integer());
}
}
Jeśli nazwa migracji jest w postaci create_junction_table_for_xxx_and_yyy_tables
lub create_junction_xxx_and_yyy_tables
,
wtedy plik będzie zawierał kod potrzebny do wygenerowania tabeli węzła pomiędzy tabelami xxx
i yyy
.
yii migrate/create create_junction_table_for_post_and_tag_tables --fields="created_at:dateTime"
generuje
/**
* Handles the creation for table `post_tag`.
* Has foreign keys to the tables:
*
* - `post`
* - `tag`
*/
class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration
{
/**
* {@inheritdoc}
*/
public function up()
{
$this->createTable('post_tag', [
'post_id' => $this->integer(),
'tag_id' => $this->integer(),
'created_at' => $this->dateTime(),
'PRIMARY KEY(post_id, tag_id)',
]);
// creates index for column `post_id`
$this->createIndex(
'idx-post_tag-post_id',
'post_tag',
'post_id'
);
// add foreign key for table `post`
$this->addForeignKey(
'fk-post_tag-post_id',
'post_tag',
'post_id',
'post',
'id',
'CASCADE'
);
// creates index for column `tag_id`
$this->createIndex(
'idx-post_tag-tag_id',
'post_tag',
'tag_id'
);
// add foreign key for table `tag`
$this->addForeignKey(
'fk-post_tag-tag_id',
'post_tag',
'tag_id',
'tag',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function down()
{
// drops foreign key for table `post`
$this->dropForeignKey(
'fk-post_tag-post_id',
'post_tag'
);
// drops index for column `post_id`
$this->dropIndex(
'idx-post_tag-post_id',
'post_tag'
);
// drops foreign key for table `tag`
$this->dropForeignKey(
'fk-post_tag-tag_id',
'post_tag'
);
// drops index for column `tag_id`
$this->dropIndex(
'idx-post_tag-tag_id',
'post_tag'
);
$this->dropTable('post_tag');
}
}
Począwszy od wersji 2.0.11, nazwy kolumn kluczy obcych dla tabeli węzła są pobierane ze schematu tabel.
Jeśli tabela nie jest zdefiniowana w schemacie, lub jej klucz główny nie jest ustawiony lub jest kluczem kompozytowym,
używana jest domyślna nazwa id
.
Przy wykonywaniu skomplikowanych migracji bazodanowych, bardzo ważnym jest zapewnienie, aby wszystkie ich operacje zakończyły się sukcesem, a w przypadku niepowodzenia nie zostały wprowadzone tylko częściowo, dzięki czemu baza danych może zachować spójność. Zalecane jest, aby w tym celu wykonywać operacje migracji wewnątrz transakcji.
Najprostszym sposobem implementacji migracji transakcyjnych jest umieszczenie ich kodu w metodach safeUp()
i safeDown()
.
Metody te różnią się od up()
i down()
tym, że są wywoływane automatycznie wewnątrz transakcji.
W rezultacie niepowodzenie wykonania dowolnej z operacji skutkuje automatycznym cofnięciem wszystkich poprzenich udanych
operacji.
W poniższym przykładzie oprócz stworzenia tabeli news
dodatkowo dodajemy pierwszy wiersz jej danych.
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration
{
public function safeUp()
{
$this->createTable('news', [
'id' => $this->primaryKey(),
'title' => $this->string()->notNull(),
'content' => $this->text(),
]);
$this->insert('news', [
'title' => 'test 1',
'content' => 'content 1',
]);
}
public function safeDown()
{
$this->delete('news', ['id' => 1]);
$this->dropTable('news');
}
}
Zwróć uwagę na to, że dodając wiele operacji bazodanowych w safeUp()
, zwykle powinieneś odwrócić kolejność ich
wykonywania w safeDown()
. W naszym przykładzie najpierw tworzymy tabelę, a potem dodajemy wiersz w safeUp()
, natomiast
w safeDown()
najpierw kasujemy wiersz, a potem usuwamy tabelę.
Uwaga: Nie wszystkie silniki baz danych wspierają transakcje i nie wszystkie rodzaje komend bazodanowych można umieszczać w transakcjach. Dla przykładu, zapoznaj się z rozdziałem dokumentacji MySQL Statements That Cause an Implicit Commit. W przypadku braku możliwości skorzystania z transakcji, powinieneś użyć
up()
idown()
.
Bazowa klasa migracji yii\db\Migration udostępnia zestaw metod, dzięki którym można połączyć się z i manipulować bazą danych. Metody te są nazwane podobnie jak metody DAO klasy yii\db\Command. Przykładowo metoda yii\db\Migration::createTable() pozwala na stworzenie nowej tabeli, tak jak yii\db\Command::createTable().
Zaletą korzystania z metod yii\db\Migration jest brak konieczności bezpośredniego tworzenia instancji yii\db\Command, a wywołanie każdej z tych metod dodatkowo wyświetli użyteczne informacje na temat operacji bazodanowych i czasu ich wykonywania.
Poniżej znajdziesz listę wspomnianych wcześniej metod:
Informacja: yii\db\Migration nie udostępnia metod dla kwerendy danych. Wynika to z tego, że zwykle nie jest potrzebne wyświetlanie dodatkowych informacji na temat pobieranych danych z bazy. Dodatkowo możesz zawsze użyć potężnego Konstruktora kwerend do zbudowania i wywołania skomplikowanych kwerend. Użycie konstruktora kwerend w migracji może wyglądać następująco:
// uaktualnij kolumnę statusu dla wszystkich użytkowników foreach((new Query)->from('users')->each() as $user) { $this->update('users', ['status' => 1], ['id' => $user['id']]); }
Aby uaktualnić bazę danych do najświeższej wersji jej struktury, należy zastosować wszystkie dostępne nowe migracje, korzystając z poniższej komendy:
yii migrate
Komenda ta wyświetli listę wszystkich migracji, które jeszcze nie zostały zastosowane. Jeśli potwierdzisz, że chcesz je
zastosować, wywoła ona metodę up()
lub safeUp()
dla każdej z migracji na liście, w kolejności ich znaczników czasu.
Jeśli którakolwiek z migracji nie powiedzie się, komenda zakończy działanie bez stosowania pozostałych migracji.
Wskazówka: Jeśli nie masz dostępu do linii komend na serwerze, wypróbuj rozszerzenie web shell.
Dla każdej udanej migracji komenda doda wiersz do bazy danych w tabeli migration
, aby oznaczyć fakt zastosowania migracji.
Pozwoli to na identyfikację, która z migracji została już zastosowana, a która jeszcze nie.
Informacja: Narzędzie do migracji automatycznie utworzy tabelę
migration
w bazie danych, wskazaną przez opcję db komendy. Domyślnie jest to baza danych określona w komponencie aplikacjidb
.
Czasem możesz mieć potrzebę zastosowania tylko jednej bądź kilku nowych migracji, zamiast wszystkich na raz. Możesz tego dokonać określając liczbę migracji, które chcesz zastosować uruchamiając komendę. Przykładowo, poniższa komenda spróbuje zastosować następne trzy dostępne migracje:
yii migrate 3
Możesz również dokładnie wskazać konkretną migrację, która powinna być zastosowana na bazie danych, używając komendy
migrate/to
na jeden z poniższych sposobów:
yii migrate/to 150101_185401 # używając znacznika czasu z nazwy migracji
yii migrate/to "2015-01-01 18:54:01" # używając łańcucha znaków, który może być sparsowany przez strtotime()
yii migrate/to m150101_185401_create_news_table # używając pełnej nazwy
yii migrate/to 1392853618 # używając UNIXowego znacznika czasu
Jeśli dostępne są niezaaplikowane migracje wcześniejsze niż ta wyraźnie wskazane w komendzie, zostaną one zastosowane automatycznie przed wskazaną migracją.
Jeśli wskazana migracja została już wcześniej zaaplikowana, wszystkie zaaplikowane aplikacje z późniejszą datą zostaną cofnięte.
Aby odwrócić (wycofać) jedną lub więcej migracji, które zostały wcześniej zastosowane, możesz uruchomić następującą komendę:
yii migrate/down # cofa ostatnio dodaną migrację
yii migrate/down 3 # cofa 3 ostatnio dodane migracje
Uwaga: Nie wszystkie migracje są odwracalne. Próba cofnięcia takiej migracji spowoduje błąd i zatrzyma cały proces.
Ponawianie migracji oznacza najpierw wycofanie jej, a potem ponowne zastosowanie. Można tego dokonać następująco:
yii migrate/redo # ponawia ostatnio zastosowaną migrację
yii migrate/redo 3 # ponawia ostatnie 3 zastosowane migracje
Uwaga: Jeśli migracja nie jest odwracalna, nie będziesz mógł jej ponowić.
Począwszy od Yii 2.0.13 możliwe jest usunięcie wszystkich tabel i kluczy obcych z bazy danych i zastosowanie wszystkich migracji od początku.
yii migrate/fresh # czyści bazę danych i wykonuje wszystkie migracje od początku
Aby wyświetlić listę wszystkich zastosowanych i oczekujących migracji, możesz użyć następujących komend:
yii migrate/history # pokazuje ostatnie 10 zastosowanych migracji
yii migrate/history 5 # pokazuje ostatnie 5 zastosowanych migracji
yii migrate/history all # pokazuje wszystkie zastosowane migracje
yii migrate/new # pokazuje pierwsze 10 nowych migracji
yii migrate/new 5 # pokazuje pierwsze 5 nowych migracji
yii migrate/new all # pokazuje wszystkie nowe migracje
Czasem zamiast aplikowania lub odwracania migracji, możesz chcieć po prostu zaznaczyć, że baza danych zostałą już uaktualniona do konkretnej migracji. Może się tak zdarzyć, gdy ręcznie modyfikujesz bazę i nie chcesz, aby migracja(e) z tymi zmianami zostały potem ponownie zaaplikowane. Możesz to osiągnąć w następujący sposób:
yii migrate/mark 150101_185401 # używając znacznika czasu z nazwy migracji
yii migrate/mark "2015-01-01 18:54:01" # używając łańcucha znaków, który może być sparsowany przez strtotime()
yii migrate/mark m150101_185401_create_news_table # używając pełnej nazwy
yii migrate/mark 1392853618 # używając UNIXowego znacznika czasu
Komenda zmodyfikuje tabelę migration
poprzez dodanie lub usunięcie wierszy, aby zaznaczyć, że baza danych ma już
zastosowane migracje aż do tej określonej w komendzie. Migracje nie zostaną faktycznie zastosowane lub usunięte.
Dostępnych jest kilka opcji pozwalających na dostosowanie komendy migracji do własnych potrzeb.
Komenda migracji ma kilka opcji, które pozwalają na zmianę jej działąnia:
interactive
: boolean (domyślnie true
), określa czy przeprowadzić migrację w trybie interaktywnym.
Jeśli ustawione jest true
, użytkownik będzie poproszony o potwierdzenie przed wykonaniem określonych operacji.
Możesz chcieć zmienić to ustawienie na false
, jeśli komenda ma być używana w tle.
migrationPath
: string|array (domyślnie @app/migrations
), określa folder, gdzie znajdują się wszystkie pliki migracji.
Parametr może być określony jako rzeczywista ścieżka lub alias.
Zwróć uwagę na to, że folder musi istnieć, inaczej okmenda może wywołać błąd. Począwszy od wersji 2.0.12 można tutaj
podać tablicę, aby załadować migracje z wielu źródeł.
migrationTable
: string (domyślnie migration
), określa nazwę tabeli w bazie danych, gdzie trzymana będzie historia
migracji. Tabela będzie automatycznie stworzona, jeśli nie istnieje.
Możesz również utworzyć ją ręcznie używając struktury version varchar(255) primary key, apply_time integer
.
db
: string (domyślnie db
), określa identyfikator bazodanowego komponentu aplikacji.
Reprezentuje on bazę danych, na której będą zastosowane migracje.
templateFile
: string (domyślnie @yii/views/migration.php
), określa ścieżkę pliku szablonu, używanego do generowania
szkieletu plików migracji. Parametr może być określony jako rzeczywista ścieżka lub alias.
Plik szablonu jest skryptem PHP, w którym możesz użyć predefiniowanej zmiennej $className
, aby pobrać nazwę klasy
migracji.
generatorTemplateFiles
: array (domyślnie `[
'create_table' => '@yii/views/createTableMigration.php',
'drop_table' => '@yii/views/dropTableMigration.php',
'add_column' => '@yii/views/addColumnMigration.php',
'drop_column' => '@yii/views/dropColumnMigration.php',
'create_junction' => '@yii/views/createTableMigration.php'
]`), określa pliki szablonów do generowania kodu migracji. Po więcej szczegółów przejdź do "Generowanie migracji".
fields
: tablica definicji kolumn w postaci łańcuchów znaków do wygenerowania kodu migracji. Domyślnie []
.
Format każdej definicji to NAZWA_KOLUMNY:TYP_KOLUMNY:DEKORATOR_KOLUMNY
. Dla przykładu,
--fields=name:string(12):notNull
generuje kolumnę typu "string" o rozmiarze 12, która nie może mieć wartości null
.
Poniższy przykład pokazuje jak można użyć tych opcji.
Chcemy zmigrować moduł forum
, którego pliki migracji znajdują się w folderze migrations
modułu - używamy następującej
komendy:
# stosuje migracje dla modułu forum w trybie nieinteraktywnym
yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0
Zamiast podawać żmudnie te same opcje za każdym razem, gdy uruchamiamy komendę migracji, można ją skonfigurować w konfiguracji aplikacji:
return [
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationTable' => 'backend_migration',
],
],
];
Powyższa konfiguracja powoduje, że z każdym uruchomieniem komendy migracji, tabela backend_migration
jest używana do
zapisu historii migracji i nie musisz już określać jej za pomocą opcji linii komend migrationTable
.
Począwszy od 2.0.10 możliwe jest używanie przestrzeni nazw w klasach migracji. Możesz zdefiniować listę przestrzeni nazw za pomocą migrationNamespaces. Korzystanie z przestrzeni nazw pozwala na łatwe używanie wielu źródeł migracji. Przykładowo:
return [
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => null, // wyłącz ścieżkę do folderu migracji, jeśli dodajesz app\migrations na liście poniżej
'migrationNamespaces' => [
'app\migrations', // Wspólne migracje dla całej aplikacji
'module\migrations', // Migracje konkretnego modułu
'some\extension\migrations', // Migracje konkretnego rozszerzenia
],
],
],
];
Uwaga: Migracje zaaplikowane z różnych przestrzeni nazw będą dodane do pojedynczej historii migracji, przez co np. niemożliwym jest zastosowanie lub cofnięcie migracji z tylko wybranej przestrzeni nazw.
Wykonując operacje na migracjach z przestrzeni nazw: dodając nowe, odwracając je, itd., należy podać pełną przestrzeń nazw
przed nazwą migracji. Zwróć uwagę na to, że odwrotny ukośnik (\
) jest zwykle uważany za znak specjalny linii komend,
zatem musisz odpowiednio zastosować symbol ucieczki, aby uniknąć błędów konsoli i niespodziewanych skutków komendy.
Dla przykładu:
yii migrate/create app\\migrations\\CreateUserTable
Uwaga: Migracje, których lokalizacja określona jest poprzez migrationPath nie mogą zawierać przestrzeni nazw. Migracje w przestrzeni nazw mogą być zaaplikowane tylko jeśli są wymienione we właściwości yii\console\controllers\MigrateController::$migrationNamespaces.
Począwszy od wersji 2.0.12 właściwość migrationPath pozwala również na podanie tablicy wymieniającej wszystkie foldery zawierające migracje bez przestrzeni nazw. Zmiana ta została wprowadzona dla istniejących projektów, które używają migracji z wielu lokalizacji, głównie z zewnętrznych źródeł jak rozszerzenia Yii tworzone przez innych deweloperów, które z tego powodu nie mogą łatwo być zmodyfikowane, aby używać przestrzeni nazw.
Migracje w przestrzeni nazw korzystają z formatu nazw "CamelCase" M<YYMMDDHHMMSS><Nazwa>
(przykładowo M190720100234CreateUserTable
).
Generując taką migrację pamiętaj, że nazwa tabeli będzie przekonwertowana z formatu "CamelCase" na format "podkreślnikowy".
Dla przykładu:
yii migrate/create app\\migrations\\DropGreenHotelTable
generuje migrację w przestrzeni nazw app\migrations
usuwającą tabelę green_hotel
, a
yii migrate/create app\\migrations\\CreateBANANATable
generuje migrację w przestrzeni nazw app\migrations
tworzącą tabelę b_a_n_a_n_a
.
Jeśli nazwa tabeli zawiera małe i wielkie litery (like studentsExam
), poprzedź nazwę podkreślnikiem:
yii migrate/create app\\migrations\\Create_studentsExamTable
To wygeneruje migrację w przestrzeni nazw app\migrations
tworzącą tabelę studentsExam
.
Czasem korzystanie z pojedynczej historii migracji dla wszystkich migracji w projekcie jest uciążliwe. Dla przykładu, możesz zainstalować rozszerzenie 'blog', zawierające całkowicie oddzielne funkcjonalności i dostarczające własne migracje, które nie powinny wpływać na te dedykowane dla funkcjonalności głównego projektu.
Jeśli chcesz, aby część migracji mogła być zastosowana i śledzona całkowicie niezależnie od pozostałych, możesz skonfigurować kilka komend migracji, które będą używać różnych przestrzeni nazw i tabeli historii migracji:
return [
'controllerMap' => [
// Wspólne migracje dla całej aplikacji
'migrate-app' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationNamespaces' => ['app\migrations'],
'migrationTable' => 'migration_app',
'migrationPath' => null,
],
// Migracje dla konkretnego modułu
'migrate-module' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationNamespaces' => ['module\migrations'],
'migrationTable' => 'migration_module',
'migrationPath' => null,
],
// Migrations dla konkretnego rozszerzenia
'migrate-rbac' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => '@yii/rbac/migrations',
'migrationTable' => 'migration_rbac',
],
],
];
Zwróć uwagę na to, że teraz, aby zsynchronizować bazę danych, musisz uruchomić kilka komend zamiast jednej:
yii migrate-app
yii migrate-module
yii migrate-rbac
Domyślnie migracje są stosowane do jednej bazy danych określonej przez
komponent aplikacji db
. Jeśli chcesz, aby były zastosowane do innej bazy, musisz
zdefiniować opcję db
w linii komend, jak poniżej,
yii migrate --db=db2
Ta komenda zastosuje migracje do bazy db2
.
Czasem konieczne jest, aby zastosować niektóre migracje do jednej bazy, a inne do drugiej. Aby to uzyskać, podczas implementacji klasy migracji należy bezpośrednio wskazać identyfikator komponentu bazy danych, który migracja ma użyć, jak poniżej:
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration
{
public function init()
{
$this->db = 'db2';
parent::init();
}
}
Ta migracja będzie zastosowana do bazy db2
, nawet jeśli w opcjach komendy określona będzie inna baza.
Zwróć uwagę na to, że historia migracji będzie uaktualniona wciąż w bazie danych określonej przez opcję db
linii komend.
Jeśli masz wiele migracji korzystających z tej samej bazy danych, zalecane jest utworzenie bazowej klasy migracji z
powyższym kodem metody init()
, a następnie dziedziczenie po niej w każdej kolejnej migracji.
Wskazówka: Oprócz ustawiania właściwości db, możesz również operować na różnych bazach poprzez tworzenie nowych połączeń bazodanowych w klasach migracji, a następnie korzystanie z metod DAO i tych połączeń.
Inną strategią migracji wielu baz danych jest utrzymywanie migracji dla różnych baz w różnych folderach migracji. Dzięki temu możesz te bazy migrować w osobnych komendach:
yii migrate --migrationPath=@app/migrations/db1 --db=db1
yii migrate --migrationPath=@app/migrations/db2 --db=db2
...
Pierwsza komenda zastosuje migracje z folderu @app/migrations/db1
na bazie db1
, druga migracje z folderu
@app/migrations/db2
na bazie db2
, itd.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.