db-migrations.md 21.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
データベースマイグレーション
============================

> Note|注意: この節はまだ執筆中です。

ソースコードと同じように、データベースの構造も、データベース駆動型のアプリケーションが開発され保守されるにともなって徐々に発展していきます。
例えば、開発中に新しいテーブルが追加されることもあるでしょうし、アプリケーションが実運用に移行した後になって追加のインデックスが必要であることが発見されることもあるでしょう。
このようなデータベースの構造的な変更 (**マイグレーション** と呼ばれます) を追跡記録することが重要であるのは、ソースコードに対する変更がバージョン管理を使って追跡記録されるのと全く同じことです。
ソースコードとデータベースの同期が失われると、バグが発生するか、アプリケーション全体が動かなくなるかします。
こうした理由によって、データベースマイグレーションツールを提供して、データベースマイグレーションの履歴の追跡管理、新しいマイグレーションの適用、また、既存のマイグレーションの取消が出来るようにしています。

下記のステップは、開発中にチームによってデータベースマイグレーションが使用される例を示すものです。

1. Tim が新しいマイグレーション (例えば、新しいテーブルを作成したり、カラムの定義を変更したりなど) を作る。
2. Tim が新しいマイグレーションをソースコントロールシステム (例えば Git や Mercurial) にコミットする。
3. Doug がソースコントロールシステムから自分のレポジトリを更新して新しいマイグレーションを受け取る。
4. Doug がマイグレーションを彼のローカルの開発用データベースに適用し、Tim が行った変更を反映して、自分のデータベースを同期する。

Yii はデータベースマイグレーションを `yii migrate` コマンドラインツールによってサポートします。
このツールは、以下の機能をサポートしています。

* 新しいマイグレーションの作成
* マイグレーションの適用、取消、再適用
* マイグレーションの履歴と新規マイグレーションの閲覧


マイグレーションを作成する
--------------------------

新しいマイグレーションを作成するためには、次のコマンドを実行します。

```
yii migrate/create <name>
```

要求される `name` パラメータには、マイグレーションの非常に短い説明を指定します。
例えば、マイグレーションが *news* という名前のテーブルを作成するものである場合は、コマンドを次のようにして使います。

```
yii migrate/create create_news_table
```

すぐ後で説明するように、マイグレーションでは、この `name` パラメータは PHP のクラス名の一部として使用されます。
したがって、アルファベット、数字、および/または、アンダースコアだけを含まなければなりません。

上記のコマンドは、`m101129_185401_create_news_table.php` という名前の新しいファイルを作成します。
このファイルは `@app/migrations` ディレクトリに作成されます。
初期状態では、このマイグレーションファイルは以下のコードを含んでいます。

```php
class m101129_185401_create_news_table extends \yii\db\Migration
{
    public function up()
    {
    }

    public function down()
    {
        echo "m101129_185401_create_news_table cannot be reverted.\n";
        return false;
    }
}
```

65
クラス名はファイル名と同じであり、`m<timestamp>_<name>` というパターンに従います。ここで、
66

67 68
* `<timestamp>` は、マイグレーションが作成された (`yymmdd_hhmmss` という書式の) UTC タイムスタンプであり、
* `<name>` は、コマンドの `name` パラメータから取られた文字列です。
69

70 71 72
クラスの中では、`up()` メソッドが、実際のデータベースマイグレーションを実装するコードを含むべきメソッドです。
言い換えると、`up()` メソッドが実際にデータベースを変更するコードを実行します。
`down()` メソッドは、`up()` によって加えられた変更を取り消すコードを含むことが出来ます。
73

74 75 76 77
場合によっては、`down()` がデータベースマイグレーションを取り消すことが出来ないことがあります。
例えば、マイグレーションがテーブルの行やテーブル全体を削除した場合は、そのデータを `down()` メソッドで復旧することは出来ません。
そのような場合には、マイグレーションは不可逆であると呼ばれ、データベースを以前の状態にロールバックすることは出来ません。
マイグレーションが不可逆である場合は、生成された上記のコードのように、`down()` メソッドは `false` を返して、マイグレーションが取り消せないものであることを示します。
78

79
例として、新しいテーブルを作成するマイグレーションを示しましょう。
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

```php

use yii\db\Schema;

class m101129_185401_create_news_table extends \yii\db\Migration
{
    public function up()
    {
        $this->createTable('news', [
            'id' => 'pk',
            'title' => Schema::TYPE_STRING . ' NOT NULL',
            'content' => Schema::TYPE_TEXT,
        ]);
    }

    public function down()
    {
        $this->dropTable('news');
    }

}
```

104 105
基底クラスである [[\yii\db\Migration]] が、データベース接続を `db` プロパティによって提供しています。
これを使って、データベースのデータとスキーマを操作することが出来ます。
106

107 108 109 110 111
この例で使われているカラムのタイプは抽象的なタイプであり、Yii によって、あなたが使用するデータベース管理システムに応じて、対応するタイプに置き換えられます。
抽象的なタイプを使うと、データベースに依存しないマイグレーションを書くことが出来ます。
例えば、`pk` は、MySQL では `int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY` に置き換えられ、sqlite では `integer PRIMARY KEY AUTOINCREMENT NOT NULL` に置き換えられます。
さらに詳細な説明と、利用可能なタイプについては、[[yii\db\QueryBuilder::getColumnType()]] のドキュメントを参照してください。
また、カラムのタイプを定義するのに、[[yii\db\Schema]] で定義されている定数を使うことも出来ます。
112

113 114
> Note|注意: テーブル定義の最後に、単純な文字列として指定された、制約やその他の特別なテーブルオプションを追加することが出来ます。
> 例えば、上記のマイグレーションでは、`content` 属性の定義の後に、`'CONSTRAINT ...'` やその他の特別なオプションを書くことが出来ます。
115 116


117 118
トランザクションを使うマイグレーション
--------------------------------------
119

120 121 122
複雑な DB マイグレーションを実行するときは、通常、データベースの一貫性と整合性を保つために、個々のマイグレーションが全体として成功または失敗することを保証する必要があります。
この目的を達成するために、DB トランザクションを利用することが出来ます。
この目的のためには、`safeUp``safeDown` という特別なメソッドを使います。
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

```php

use yii\db\Schema;

class m101129_185401_create_news_table extends \yii\db\Migration
{
    public function safeUp()
    {
        $this->createTable('news', [
            'id' => 'pk',
            'title' => Schema::TYPE_STRING . ' NOT NULL',
            'content' => Schema::TYPE_TEXT,
        ]);

        $this->createTable('user', [
            'id' => 'pk',
            'login' => Schema::TYPE_STRING . ' NOT NULL',
            'password' => Schema::TYPE_STRING . ' NOT NULL',
        ]);
    }

    public function safeDown()
    {
        $this->dropTable('news');
        $this->dropTable('user');
    }

}
```

154
使用するクエリが一つだけでない場合は、`safeUp``safeDown` を使うことを推奨します。
155

156 157 158 159
> Note|注意: 全ての DBMS がトランザクションをサポートしている訳ではありません。
> また、トランザクションに入れることが出来ない DB クエリもあります。
> その場合には、代りに、`up()` と `down()` を実装しなければなりません。
> また、MySQL の場合は、[暗黙のコミット](http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html) を引き起こす SQL 文があります。
160 161


162 163
マイグレーションを適用する
--------------------------
164

165
利用できる全ての新しいマイグレーションを適用する (すなわち、ローカルのデータベースを最新の状態にする) ためには、次のコマンドを実行します。
166 167 168 169 170

```
yii migrate
```

171 172 173 174 175 176
コマンドを実行すると、すべての新しいマイグレーションが一覧表示されます。
マイグレーションを適用することを確認すると、クラス名のタイムスタンプの値の順に、一つずつ、すべての新しいマイグレーションクラスの `up()` メソッドが実行されます。

マイグレーションを適用した後に、マイグレーションツールは `migration` という名前のデータベーステーブルに記録を残します。
これによって、ツールは、どのマイグレーションが適用済みで、どのマイグレーションが適用されていないかを特定することが出来ます。
`migration` テーブルが存在しない場合は、ツールは `db` [アプリケーションコンポーネント](structure-application-components.md)によって指定されたデータベースの中にテーブルを自動的に作成します。
177

178
時として、新しいマイグレーションを一個また数個だけ適用したい場合があります。その場合は、次のコマンドを使うことが出来ます。
179 180 181 182 183 184


```
yii migrate/up 3
```

185
このコマンドは、次の新しいマイグレーションを 3 個適用します。3 という値を変更して、適用されるマイグレーションの数を変更することが出来ます。
186

187
また、下記のコマンドを使って、特定のバージョンまでデータベースをマイグレートすることも可能です。
188 189 190 191 192

```
yii migrate/to 101129_185401
```

193 194 195
すなわち、マイグレーション名のタイムスタンプ部分を使って、データベースをマイグレートして到達したいバージョンを指定します。
最後に適用されたマイグレーションと指定されたマイグレーションの間に複数のマイグレーションがある場合は、それらのマイグレーションがすべて適用されます。
指定されたマイグレーションが適用済みである場合は、その後に適用されたすべてのマイグレーションが取り消されます (次の節で説明します)。
196 197


198 199 200 201
マイグレーションを取り消す
--------------------------

適用された最後のマイグレーション (一個または複数個) を取り消したい場合は、下記のコマンドを使うことが出来ます。
202 203 204 205 206 207


```
yii migrate/down [step]
```

208 209
ここで、オプションの `step` パラメータは何個のマイグレーションを取り消すかを指定するものです。
デフォルト値は 1 で、適用された最後のマイグレーションだけが取り消すされることを意味します。
210

211 212
前に説明したように、全てのマイグレーションが取り消せるとは限りません。
取り消せないマイグレーションを取り消そうとすると例外が投げられて、取り消しのプロセス全体が終了させられます。
213 214


215 216
マイグレーションを再適用する
----------------------------
217

218 219
マイグレーションの再適用とは、指定されたマイグレーションを最初に取り消してから、再度適用することを意味します。
これは次のコマンドによって実行することが出来ます。
220 221 222 223 224

```
yii migrate/redo [step]
```

225 226
ここで、オプションの `step` パラメータは何個のマイグレーションを再適用するかを指定するものです。
デフォルト値は 1 で、最後のマイグレーションだけが再適用されることを意味します。
227 228


229 230 231 232
マイグレーション情報を表示する
------------------------------

マイグレーションを適用したり取り消したりする他に、マイグレーションツールはマイグレーションの履歴、および、まだ適用されていない新しいマイグレーションを表示することも出来ます。
233 234 235 236 237 238 239


```
yii migrate/history [limit]
yii migrate/new [limit]
```

240 241
ここで、オプションの `limit` パラメータは、何個のマイグレーションを表示するかを指定するものです。
`limit` が指定されない場合は、利用可能な全てのマイグレーションが表示されます。
242

243
最初のコマンドは適用済みのマイグレーションを表示し、第二のコマンドはまだ適用されていないマイグレーションを表示します。
244 245


246 247
マイグレーション履歴を修正する
------------------------------
248

249 250 251
時として、実際には関係のあるマイグレーションを適用または取り消すことなく、マイグレーション履歴を特定のマイグレーションバージョンに修正したい場合があります。
このことは新しいマイグレーションを開発するときにしばしば起ります。
次のコマンドを使ってこの目的を達することが出来ます。
252 253 254 255 256

```
yii migrate/mark 101129_185401
```

257
このコマンドは `yii migrate/to` コマンドと非常によく似ていますが、マイグレーションを適用または取り消すことなく、マイグレーション履歴テーブルを指定されたバージョンに修正することだけを行うという点で違っています。
258 259


260 261
マイグレーションコマンドをカスタマイズする
------------------------------------------
262

263
マイグレーションコマンドをカスタマイズする方法がいくつかあります。
264

265
### コマンドラインオプションを使う
266

267
マイグレーションコマンドには、コマンドラインで指定できるいくつかのオプションがあります。
268

269 270 271
* `interactive`: 真偽値。マイグレーションを対話モードで実行するかどうかを指定します。
  デフォルト値は true で、指定されたマイグレーションを実行するときに、ユーザは何らかの入力を促されます。
  このオプションを false にセットして、マイグレーションがバックグラウンドプロセスとして実行されるようにすることが出来ます。
272

273 274 275
* `migrationPath`: 文字列。全てのマイグレーションクラスファイルを保存しているディレクトリを指定します。
  このパスは、パスエイリアスの形式で指定されなければならず、また、対応するディレクトリが存在する必要があります。
  このオプションが指定されない場合は、アプリケーションのベースパスの下の `migrations` サブディレクトリが使われます。
276

277 278
* `migrationTable`: 文字列。マイグレーション履歴の情報を保存するためのデータベーステーブル名を指定します。
  デフォルト値は `migration` です。このテーブルは、`version varchar(255) primary key, apply_time integer` という構造を持ちます。
279

280 281
* `db`: 文字列。データベース [アプリケーションコンポーネント](structure-application-components.md) の ID を指定します。
  デフォルト値は 'db' です。
282

283 284 285 286
* `templateFile`: 文字列。マイグレーションクラスを生成するためのコードテンプレートとして使われるファイルのパスを指定します。
  このパスは、パスエイリアスの形式で指定しなければなりません (例えば、`application.migrations.template`)。
  指定されない場合は、内部テンプレートが使用されます。
  テンプレートの中の `{ClassName}` というトークンが実際のマイグレーションクラス名によって置き換えられます。
287

288
これらのオプションを指定するためには、下記の書式を使って migrate コマンドを実行します。
289 290 291 292 293

```
yii migrate/up --option1=value1 --option2=value2 ...
```

294 295
例えば、`forum` モジュールのためのマイグレーションを実行するときに、マイグレーションファイルがモジュールの `migrations` ディレクトリに置かれている場合には、下記のコマンドを使うことが出来ます。

296 297 298 299 300 301

```
yii migrate/up --migrationPath=@app/modules/forum/migrations
```


302 303 304 305 306
### コマンドをグローバルに構成する

コマンドラインオプションを使ってマイグレーションコマンドをその場その場で構成することも出来ますが、場合によっては、一度にまとめてコマンドを構成しておきたいこともあります。
例えば、マイグレーションの履歴を保存するのに別のテーブルを使用したいとか、カスタマイズしたマイグレーションテンプレートを使用したいとかです。
そうするためには、コンソールアプリケーションの構成情報ファイルを以下のように修正します。
307 308 309 310 311 312 313 314 315 316 317


```php
'controllerMap' => [
    'migrate' => [
        'class' => 'yii\console\controllers\MigrateController',
        'migrationTable' => 'my_custom_migrate_table',
    ],
]
```

318 319
これで、`migrate` コマンドを実行すると、上記の構成情報が効果を発揮して、毎回コマンドラインオプションを入力する必要がなくなります。
その他のコマンドラインオプションも、このようにして構成することが出来ます。
320 321


322
### 複数のデータベースのマイグレーション
323

324 325
既定では、マイグレーションは `db` [アプリケーションコンポーネント](structure-application-components.md) によって指定されるデータベースに対して適用されます。
これは、`--db` オプションを指定することによって変更することが出来ます。例えば、
326 327 328 329 330

```
yii migrate --db=db2
```

331
上記のコマンドは、既定のマイグレーションパスに置かれている *全ての* マイグレーションを `db2` データベースに適用するものです。
332

333 334
アプリケーションが複数のデータベースを扱っている場合は、いくつかのマイグレーションはあるデータベースに適用されなければならず、他のマイグレーションは別のデータベースに適用されなければならない、ということがあり得ます。
そのような場合には、異なるデータベースごとに基底マイグレーションクラスを作成して、下記のように [[yii\db\Migration::init()]] メソッドをオーバーライドすることを推奨します。
335 336 337 338 339 340 341 342 343

```php
public function init()
{
    $this->db = 'db2';
    parent::init();
}
```

344 345
こうすると、特定のデータベースに適用されるべきマイグレーションを作成するためには、対応する基底マイグレーションクラスから拡張するだけで済みます。
これで、`yii migrate` コマンドを実行すると、全てのマイグレーションはそれぞれ対応するデータベースに対して適用されるようになります。
346

347 348
> Info|情報: それぞれのマイグレーションはハードコードされた DB 接続を使用しますので、`migrate` コマンドの `--db` オプションは効果を持ちません。
  また、マイグレーション履歴はデフォルトの `db` データベースに保存されることに注意してください。
349

350
`--db` オプションによる DB 接続の変更をサポートしたい場合は、次のような別の方法で複数のデータベースを扱うことが出来ます。
351

352 353
それぞれのデータベースについて、マイグレーションパスを作成し、対応する全てのマイグレーションクラスをそこに保存します。
マイグレーションを適用するためには、次のようなコマンドを実行します。
354 355 356 357 358 359 360

```
yii migrate --migrationPath=@app/migrations/db1 --db=db1
yii migrate --migrationPath=@app/migrations/db2 --db=db2
...
```

361
> Info|情報: 上記の方法では、マイグレーション履歴は `--db` オプションによって指定された別々のデータベースに保存されます。