mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-04 07:14:06 +01:00
305 lines
10 KiB
Plaintext
305 lines
10 KiB
Plaintext
Datenbankmigration
|
|
==================
|
|
|
|
> Note|Hinweis: Das Feature zur Datenbankmigration ist seit Verison 1.1.6 verfügbar.
|
|
|
|
Genause wie der Quelltext einer Anwendung verändert sich auch die Struktur der
|
|
zugehörigen Datenbank während der Entwicklung. So muss z.B. irgendwann eine Tabelle
|
|
hinzugefügt werden. Oder nachdem die Anwendung produktiv geschaltet wurde,
|
|
stellt man fest, dass eine Spalte noch dringend einen Index benötigt. Es ist
|
|
daher genauso wichtig wie beim Quelltext, dass auch die strukturellen Änderungen
|
|
in der Datenbank festgehalten werden (man spricht hier auch von **Migration**).
|
|
Wenn Programmcode und Datenbank nicht mehr zueinander passen, ist ein
|
|
Fehlverhalten praktisch vorprogrammiert. Yii enthält daher ein Tool zur
|
|
Datenbankmigration, dass eine Historie von Migrationen verwalten, neue
|
|
Migrationen durchführen oder existierende rückgangig machen kann.
|
|
|
|
Der folgende Ablauf soll verdeutlichen, wie Datenbanmigration bei der
|
|
Entwicklung eingesetzt wird:
|
|
|
|
1. Tim erstellt eine Migration (er erstellt z.B. eine neue Tabelle)
|
|
2. Tim überträgt seine Änderung in ein Versionskontrollsystem (z.B. SVN, GIT)
|
|
3. Doug updated seine Arbeitskopie und erhält die neue Migration
|
|
4. Doug wendet die Migration auf seiner lokalen Datenbank an
|
|
|
|
Migrationen werden in Yii über den Kommandozeilenbefehl `yiic migrate`
|
|
verwaltet. Mit diesem Befehl können neue Migrationen erstellt, angewendet,
|
|
zurückgenommen oder wiederholt werden. Man kann auch die Historie aller
|
|
Migrationen oder neue Migrationen anzeigen lassen.
|
|
|
|
Migrationen erstellen
|
|
---------------------
|
|
|
|
Um eine neu Migration (z.B. zum Anlegen einer News-Tabelle) zu erzeugen,
|
|
verwendet man folgenden Befehl:
|
|
|
|
~~~
|
|
yiic migrate create <name>
|
|
~~~
|
|
|
|
Der Parameter `name` dient dazu, die Migration kurz und knapp zu beschreiben
|
|
(z.B. `erstelle_news_tabellle`). Wie wir weiter unten zeigen, wird dieser
|
|
Name Bestandteil eines PHP-Klassennamens werden. Er sollte daher nur
|
|
Buchstaben, Zahlen und/oder Unterstriche enthalten.
|
|
|
|
~~~
|
|
yiic migrate create erstelle_news_tabelle
|
|
~~~
|
|
|
|
Damit wird im Verzeichnis `protected/migrations` eine Datei
|
|
`m101129-185401_erstelle_news_tabelle.php` mit diesem Inhalt erzeugt:
|
|
|
|
~~~
|
|
[php]
|
|
class m101129_185401_erstelle_news_tabelle extends CDbMigration
|
|
{
|
|
public function up()
|
|
{
|
|
}
|
|
|
|
/*
|
|
public function down()
|
|
{
|
|
}
|
|
*/
|
|
}
|
|
~~~
|
|
|
|
Beachten Sie, dass der Klassenname dem Dateinamen entspricht und dem Muster
|
|
`m<zeitstempel>_<name>` folgt, wobei `<zeitstempel>` für den UTC-Zeitstempel (im
|
|
Format `JJMMTT_HHMMSS`) des Erstellzeitpunkts und `<name>` für den obigen
|
|
Migrationsnamen steht.
|
|
|
|
Die `up()`-Methode sollte den Code für die eigentliche Migration enthalten,
|
|
`down()` den Code, um die Änderung rückgängig zu machen.
|
|
|
|
Manchmal kommt es vor, dass eine `down()`-Methode nicht möglich ist, zum
|
|
Beispiel wenn in `up()` einige Tabellenzeilen gelöscht wurden. In diesem Fall
|
|
wird die Migration irreversibel genannt. Man kann sie also nicht rückgängig
|
|
machen und die Datenbank in einen früheren Zustand zurückfahren.
|
|
|
|
Das folgende Beispiel zeigt die Migration zum Erstellen einer News-Tabelle.
|
|
|
|
~~~
|
|
[php]
|
|
class m101129_185401_erstelle_news_tabelle extends CDbMigration
|
|
{
|
|
public function up()
|
|
{
|
|
$this->createTable('tbl_news', array(
|
|
'id' => 'pk',
|
|
'title' => 'string NOT NULL',
|
|
'content' => 'text',
|
|
));
|
|
}
|
|
|
|
public function down()
|
|
{
|
|
$this->dropTable('tbl_news');
|
|
}
|
|
}
|
|
~~~
|
|
|
|
Die Basisklasse [CDbMigration] stellt einige Methoden zum Manipulieren von
|
|
Daten und DB-Schemas bereit. Mit [CDbMigration::createTable] kann man zum
|
|
Beispiel eine Tabelle erzeugen, während [CDbMigration::insert] Zeilen in eine
|
|
Tabelle einfügt. Alle Methoden verwenden die Datenbankverbindung, die von
|
|
[CDbMigration::getDbConnection()] zurückgeliefert wird. Standardmäßig ist das
|
|
`Yii::app()->db`.
|
|
|
|
> Info|Info: Sie werden feststellen, dass die DB-Methoden von [CDbMigration]
|
|
> denen von [CDbCommand] sehr ähneln. Sie sind tatsächlich auch fast
|
|
> identisch, außer, dass bei den [CDbMigration]-Methoden zusätzlich die
|
|
> Zeit gemessen, sowie einige Informationen über die Parameter ausgegeben
|
|
> werden.
|
|
|
|
|
|
Migrationen anwenden
|
|
--------------------
|
|
|
|
Um alle verfügbaren neuen Migrationen anzuwenden (um die lokale Datenbank also
|
|
auf den aktuellsten Stand zu bringen) ruft man diesen Befehl auf:
|
|
|
|
~~~
|
|
yiic migrate
|
|
~~~
|
|
|
|
Der Befehl listet alle neuen Migrationen auf. Bestätigt man die Durchführung
|
|
der Migrationen, werden sämtliche `up()`-Methoden aller neuen
|
|
Migrationsklassen ausgeführt. Die Reihenfolge entspricht dabei dem Zeitstempel im
|
|
Klassennamen.
|
|
|
|
Nachdem eine Migration angewendet wurde, speichert das Migrationstool dazu einen
|
|
Datensatz in einer Tabelle namens `tbl_migration`. Das ermöglicht dem Tool,
|
|
festzustellen, welche Migrationen schon angewendet wurden und welche nicht.
|
|
Falls die Tabelle `tbl_migration` nicht existiert, wird das Tool sie
|
|
automatisch anlegen und zwar in der Datenbank, die in der `db`-Komponente
|
|
konfiguriert wurde.
|
|
|
|
Manchmal kommt es vor, dass man nur eine oder wenige Migrationen durchführen
|
|
möchte. Das geht mit diesem Befehl:
|
|
|
|
~~~
|
|
yiic migrate up 3
|
|
~~~
|
|
|
|
Damit werden 3 neuen Migrationen angewendet. Die Zahl bestimmt also, wieviele
|
|
Migrationen man anwenden möchte.
|
|
|
|
Man kann die Datenbank mit folgendem Befehl auch auf eine bestimmte Version migrieren:
|
|
|
|
~~~
|
|
yiic migrate to 101129_185401
|
|
~~~
|
|
|
|
Man gibt also den Zeitstempel-Teil des Migrationsnamen an, um die Version zu
|
|
spezifizieren, zu der man migrieren möchte. Sämtliche Migrationen zwischen der
|
|
aktuellen lokalen DB-Version und dem angegebenen Zeitstempel werden somit
|
|
durchgeführt. Wurde die angegebene Migration bereits durchgeführt, so werden
|
|
alle späteren Migrationen rückgängig gemacht (siehe unten).
|
|
|
|
|
|
Migrationen rückgängig machen
|
|
-----------------------------
|
|
|
|
Um die letzte(n) angewendete(n) Migration(en) rückgängig zu machen, kann man
|
|
folgenden Befehl verwenden:
|
|
|
|
~~~
|
|
yiic migrate down [schritt]
|
|
~~~
|
|
|
|
wobei der optionale `schritt`-Paramter angibt, wie viele Migrationen man
|
|
rückgängig machen möchte. Standardmäßig steht er auf 1, wodurch die letzte
|
|
Migration zurückgefahren wird.
|
|
|
|
Wie oben erwähnt, können nicht alle Migrationen rückgängig gemacht werden.
|
|
Versucht man eine irreversible Migration rückgängig zu machen, wird eine
|
|
Exception geworfen und der gesamte Prozess beendet.
|
|
|
|
Migrationen wiederholen
|
|
-----------------------
|
|
|
|
Migrationen zu wiederholen bedeutet, sie erst rückgängig zu machen und dann
|
|
erneut anzuwenden. Das geschieht mit diesem Befehl:
|
|
|
|
~~~
|
|
yiic migrate redo [schritt]
|
|
~~~
|
|
|
|
wobei der optionale `schritt`-Parameter wieder angibt, wie viele Migrationen
|
|
wiederholt werden sollen. Standardmäßig wird auch hier die letzte Migration
|
|
wiederholt.
|
|
|
|
Anzeigen von Migrationsinformationen
|
|
------------------------------------
|
|
|
|
Das Tool kann nicht nur Migrationen anwenden und rückgängig machen, sondern
|
|
auch die Historie der durchgeführten Migrationen bzw. die Liste der neuen
|
|
Migrationen anzeigen.
|
|
~~~
|
|
yiic migrate history [limit]
|
|
yiic migrate new [limit]
|
|
~~~
|
|
|
|
Der optionale Parameter `limit` gibt an, wieviele Migrationen maximal
|
|
angezeigt werden sollen. Wird er weggelassen, werden alle Migrationen
|
|
angezeigt.
|
|
|
|
Der erste Befehl zeigt alle angewendenten Migrationen, der zweite die Liste
|
|
der neuen, die noch nicht durchgeführt wurden.
|
|
|
|
|
|
Ändern der Migrations-Historie
|
|
------------------------------
|
|
|
|
Es kommt vor, dass man die Migrationshistorie auf eine bestimmte Version
|
|
setzen möchte, ohne die Migration tatsächlich durchzführen oder
|
|
zurückzufahren. Gerade wenn man eine neue Migration erstellt ist dies häufig
|
|
der Fall. Dazu dient der folgende Befehl:
|
|
|
|
~~~
|
|
yiic migrate mark 101129_185401
|
|
~~~
|
|
|
|
Der Befehl ist ähnlich zu `yiic migrate to`, außer, dass er nur die
|
|
Migrationshistorie auf die angegebene Version setzt, ohne Migrationen
|
|
durchzuführen oder zurückzufahren.
|
|
|
|
Anpassen des Migrationsbefehls
|
|
------------------------------
|
|
|
|
Der Migrationsbefehl kann auf verschiedene Arten angepasst werden.
|
|
|
|
### Über Kommandozeilen-Optionen
|
|
|
|
Der Migrationsbefehl kennt vier Optionen, die an der Kommandozeile angegeben
|
|
werden können:
|
|
|
|
* `interactive`: boolean, gibt an, ob die Migrationen im interaktiven Modus
|
|
ausgeführt werden soll, was standardmäßig der Fall ist. Der Anwender wird so
|
|
vor der Durchführung einer Migration gefragt. Setzt man die Option auf `false`
|
|
wird die Migration im Hintergrund durchgeführt.
|
|
|
|
* `migrationPath`: string, legt das Verzeichnis mit allen Migrationsdateien
|
|
fest. Es muss ein Pfadalias angegeben werden, der auf ein existierendes
|
|
Verzeichnis verweist. Wird nichts angegeben, wird das
|
|
`migrations`-Unterverzeichnis im Basispfad verwendet.
|
|
|
|
* `migrationTable`: string, gibt den Namen der Tabelle für die
|
|
Migrationshistorie an. Vorgabewert ist `tbl_migration`. Die Tabellenstruktur
|
|
ist `version varchar(255) primary key, apply_time integer`.
|
|
|
|
* `connectionID`: string, die ID der DB-Komponenten. Standardmäßig 'db'.
|
|
|
|
* `templateFile`: string, gibt den Pfadalias zu einer Vorlagendatei für neue
|
|
Migrationsklassen an (z.B. `application.migrations.template`). Wird diese
|
|
Option nicht angegeben, wird eine interne Vorlage verwendet. Innerhalb des
|
|
Templates wird der Token `{ClassName}` später mit dem eigentlichen
|
|
Klassennamen ersetzt.
|
|
|
|
Diese Optionen können wie folgt angegeben werden:
|
|
|
|
~~~
|
|
yiic migrate up --option1=value1 --option2=value2 ...
|
|
~~~
|
|
|
|
Will man zum Beispiel ein Modul `forum` migrieren, dessen Migrationsdateien im
|
|
`migrations`-Verzeichnis des Moduls zu finden sind, eignet sich dieser Befehl:
|
|
|
|
~~~
|
|
yiic migrate up --migrationPath=ext.forum.migrations
|
|
~~~
|
|
|
|
|
|
### Über globale Konfiguration des Befehls
|
|
|
|
Während man mit den Kommandozeilenoptionen die Migration direkt beeinflussen
|
|
kann, ist es manchmal einfacher, die Konfiguration einmalig für alle Aufrufe
|
|
zu verändern. Evtl. möchte man ja eine andere Tabelle für die
|
|
Migrationshistorie oder eine angepasste Vorlage verwenden. Dazu kann man die
|
|
Konfiguration für Konsolenanwendungen folgendermaßen anpassen:
|
|
|
|
~~~
|
|
[php]
|
|
return array(
|
|
......
|
|
'commandMap'=>array(
|
|
'migrate'=>array(
|
|
'class'=>'system.cli.commands.MigrateCommand',
|
|
'migrationPath'=>'application.migrations',
|
|
'migrationTable'=>'tbl_migration',
|
|
'connectionID'=>'db',
|
|
'templateFile'=>'application.migrations.template',
|
|
),
|
|
......
|
|
),
|
|
......
|
|
);
|
|
~~~
|
|
|
|
Ruft man nun den `migrate`-Befehl auf, werden obige Optionen immer angewendet,
|
|
ohne sie explizit mit angeben zu müssen.
|
|
|
|
<div class="revision">$Id: database.migration.txt 2832 2011-01-10 14:37:04Z qiang.xue $</div>
|