[CodeIgniter] Migrationクラスの動きを確認してみた

DBの設定をファイルで管理できるマイグレーション。CodeIgniterにも標準でMigrationライブラリクラスが搭載されています。今回は、CodeIgniterのMigrationライブラリクラスの動きを確認してみました。

Migrationライブラリクラスの全体的な流れ

CodeIgniterでマイグレーションを使う場合は、

  1. Migration用のコントローラーを読み出す
  2. $config[‘migration_version’]に設定されたバージョンのマイグレーションファイルを読み込む
    ($config[‘migration_path’]で設定したディレクトリの中から)
  3. 処理(up、downなど)する

という流れで実行されます。

実際のコードは、CodeIgniter公式ガイドのサンプルプログラムや、こちらの記事がわかりやすいです。

それぞれの処理の動作をみてみる

次に、実際にバージョンアップやロールバックをする際にどのように動いているかを見ていきます。

以下のマイグレーションファイルがある想定です。

application
  └── migration
        └── 001_my_table1.php
        └── 002_my_table2.php
        └── 003_my_table3.php
        └── 004_my_table4.php
        └── 005_my_table5.php

わかりやすくするためにファイル名を数字にしていますが、CodeIgniter3以降は数字は非推奨でtimestampが推奨されています。

ファイル名やクラス名のルールに注意

CodeIgniterのマイグレーションライブラリは、クラス名とファイルは推測されて実行されるので、合わせる必要があります。

例:001_my_table1.php ==> Migration_My_Table1クラス

ファイル名の「番号」以降の部分と、クラス名の「Migration」以降の部分が一致しないと動きません。

最新版にアップデート($this->migration->current())する時の動き

普通に最新版にする時の場合です。

流れ的には、

  1. $config[‘migration_version’]に設定されたバージョンのまでのマイグレーションファイルをリストアップ
  2. それぞれのupメソッドを実行

という感じになっています。

例えば、マイグレーション前のversionが3で、migration_versionが5なら、

  1. 004_my_table.phpのupメソッドを実行
  2. 005_my_table.phpのupメソッドを実行

という形でバージョンアップしていきます。

ロールバック/バージョン指定した変更($this->migration->version($version))する時の動き

「$this->migration->version($version)」は、指定のバージョンに戻す時のメソッドです。ロールバックする際もこのメソッドが使われます。

動きとしては、

  1. 指定した$versionの一つ前のバージョンまでのupメソッドもしくはdownメソッドを実行

という動きになります。

バージョンアップする時

例えば、currentが2で$versionを5とした時、3,4,5のそれぞれのupメソッドが順々に行われます。

バージョンダウン(ロールバック)する時

逆にロールバックする場合、例えばcurrentが5で$versionを2に戻すと言った時は、5,4,3の順番で、それぞれのdownメソッドが行われます。

マイグレーションクラスを利用する時に注意したいポイント

簡単に設定ができるCodeIgniterのマイグレーションですが、注意すべき点もいくつかあります。

同じクラス名は使えない

今回の例のファイル構成で、なぜ「番号_my_table」のあとに数字をつけているかというと、CodeIgniterのマイグレーションクラスでは同じクラス名を使えないというルールがあるためです。

厳密には使えなくもないんですが、バージョンを1つだけ上げる・下げる時にしか使えません。これまで見てきたバージョン2から5にあげる時にように、複数のマイグレーションを実行する際には「クラス目が重複している」とエラーが出てしまいます。

エラーを回避するためには、必ずクラス名を重複しないようにします。

001_my_table1.phpの例

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
  class Migration_My_Table1 extends CI_Migration {
.
.
.

002_my_table2.phpの例

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
  class Migration_My_Table2 extends CI_Migration {
.
.
.

管理は面倒ですが、「201710111200_my_table1.php」のように、「時間_テーブル名+数字.php」のようにクラス&ファイル名をつける感じになりそうです。

upメソッドを書いたらしったりdownメソッドも書く

ロールバックというと、プログラムが自動的に差分を解析したり、バックアップデータを使って元に戻してくれそうなイメージですが、基本的にはdownメソッドを行うだけです。

ですので、しっかりとdownメソッドも矛盾しないように記述をしないとあとで痛い目にあいます。

マイグレーションは基本的にはバージョンアップで使うことが多いので、upメソッドをメインに書いていくことになりますが、マイグレーションを使う時は前のマイグレーションファイルとの差分を考えてdownを記述する必要があります。

データベースによっては使えないメソッドがある

ほとんどの人はCodeIgniterでのデータベースではMYSQLかと思いますが、例えばSQLiteを使っている場合、drop_columnなどのメソッドが使えません。

これは、SQLiteにはMYSQLでいう「ALTER TABLE テーブル DROP カラム」コマンドがないためです(カラムの追加はできます)。

この点を想定してマイグレーションを行わないと、例えばSQLiteのデータベースを使ったシステムで、

  1. バージョンアップでadd_columnでカラムを追加
  2. エラーが見つかったので、ロールバックで1つ前のバージョンに戻す(現バージョンのdownメソッドで「drop_column」を実行)
  3. SQLiteだとカラムを消せないので戻せない
  4. SQLiteだとテーブルを消した後に「VACUUM」しないと再度テーブルが作れない

ということになります。


ざっくりとですが、CodeIgniterのマイグレーションクラスの挙動をあげてみました。

簡単に使えて複数環境で同じテーブルを作成できるマイグレーション。使いこなせば開発がより効率的になりそうですね。