ブログ

ryuzeeによるブログ記事。不定期更新

CakePHP2系でマイグレーションを利用する方法

マイグレーションを使わないで、データベースのスキーマ構成を変更したりすると、特に複数人で開発しているような場合にこんなことが起こったりします。

  • 自分の開発マシンとテストサーバ等でスキーマ構成が違っている
  • さらには他人の開発マシンともスキーマ構成が異なっている
  • しかもどっちがあっているか分からない
  • 例えば、みんなが色々変更しているせいで、カラムの順番が入れ子になってたりする
  • 本番サーバに反映しようとした時に、どの順番にスキーマ変更を行ったらよいか分からない。
  • ソースコードのリリースバージョンと紐付くデータベースの状態がよく分からない。

こういう本質的でないことに時間を使っては勿体無いので、データベースの構成管理にはマイグレーション機能を使うのが定石です。Railsなんかだと当たり前なのですが、今回はCakePHP2系でマイグレーションを利用する方法を紹介します。

CakeDC Migrationの導入

CakePHPでマイグレーションを行う場合は、CakeDCが開発しているMigrations Plugin for CakePHPを使うのが定番です。 入手はhttps://github.com/CakeDC/migrationsから可能です。

今回はgitコマンドを使ってsub moduleとして登録します。

cd [プロジェクトのディレクトリ]
git submodule add \
git://github.com/CakeDC/migrations.git app/Plugin/Migrations

これによって、app/Plugin/Migrations以下に配置されます。 このままだと使えないので、app/Config/bootstrap.php に以下を追記します。 既に他のプラグインをロードするようになっている場合は既存の配列にMigrationsを追加します。

CakePlugin::load(array('Migrations'));

使い方の手順

CakeDCのMigrationを利用してマイグレーションファイルを作成する際には2つの方法が可能です。

  1. 自分のローカルの開発環境のデータベースに変更を加え、その変更内容から自動でマイグレーションファイルを作成する。
  2. マイグレーションのひな形作成機能だけを使ってマイグレーションの中身を自分で書く。

いずれの場合も作ったマイグレーションファイルをバージョン管理システムに登録すれば、他の環境でもすぐに同じ変更を反映することができます。

初期マイグレーションの作成

まず、現在のデータベースからバージョン1のマイグレーションを作成します。

作業の開始前にまず、マイグレーションを管理するためのテーブルを以下のコマンドで作っておきます。

Console/cake Migrations.migration run all -p

次に初期マイグレーションを作りますが、app/Config/Schema/schema.php が既に存在している場合は、内容の比較を行なってしまうため、一端ファイルを削除します。 その上で以下のコマンドを実行します。引数に-fをつけるのは、モデルが存在しないテーブルも含めたマイグレーションファイルを作成するためです。

Console/cake Migrations.migration generate -f

コマンドを実行すると、

Do you want generate a dump from current database? (y/n)

と聞かれます。これはマイグレーションを作る歳に、まだschema.phpがないため、現在のデータベースを丸々dumpするかを聞いているので、yを選択します。

次に

Do you want to preview the file before generation? (y/n)

と聞かれます。これはこれから作るマイグレーションファイルのプレビュー機能なので、内容を見たければyを選択してください。内容が思ったとおりでない場合はCtrl+Cで抜けられます。

コマンドの最後に

Please enter the descriptive name of the migration to generate:

と聞かれますので、マイグレーションファイルにつける名前を入力します。拡張子等は不要です。また実際に作られたファイルの先頭にはタイムスタンプが自動で付与され、このタイムスタンプが実行順序を制御します。

これで初期のマイグレーションファイルが作られました。

また現在のデータベースのスキーマを以下のコマンドで作成します。これによってConfig/Schema/schema.phpが現在のデータベースの状態で作成されます。以降自動生成する場合はこのschema.phpと接続先データベースとの比較の機能を利用するためです。

Console/cake schema generate –f

新たなマイグレーションファイルを作る

ここまでで初期のマイグレーションファイルができ上がったので、後はデータベースの変更にあわせて都度マイグレーションを作成していくだけです。 先に述べたように、先にデータベースに変更を加えてそこからマイグレーションを自動生成する方法とスケルトンだけ作成して自分で内容を記述する方法があります。

1. データベースを変更してからマイグレーションを作成する方法

では適当なテーブルを作って、そこからマイグレーションを作ってみます。 まず、データベースで適当にテーブルを作ります。

create table projects
(
  id int auto_increment primary key,
  name varchar(100) not null comment 'プロジェクト名'
);

次にマイグレーションを作ります。コマンドは初期作成時と同じです。

Console/cake Migrations.migration generate -f

このコマンドを実行すると、初期マイグレーションの時と違って以下のようなメッセージが表示されます。

Do you want compare the schema.php file to the database? (y/n)

これは現在のデータベースとschema.phpを比較して差分をマイグレーションとして作成するかどうかを聞いているのでyを選択します。次に先ほどと同じように作成内容をプレビューするかどうか聞いてきますので適宜選択し、最後に保存ファイル名を入力します。どんな変更をしているのか明確になるような名前を入れます。ここではprojectsテーブルの追加なので、add_projects_tableとします。

Please enter the descriptive name of the migration to generate:
> add_projects_table

さらに最後に、以下のように、既存のschema.phpを上書きするかどうか聞いてきますので、yを選択して、schema.phpを最新化します。既にschema.phpが存在しているので、最後の上書き確認ではOを選択します。

Do you want update the schema.php file? (y/n)
[y] > y

Welcome to CakePHP v2.2.3 Console
---------------------------------------------------------------
App : app
Path: /Users/ryuzee/dev/project/cake2_sample/app/
---------------------------------------------------------------
Cake Schema Shell
---------------------------------------------------------------
Generating Schema...
Schema file exists.
 [O]verwrite
 [S]napshot
 [Q]uit
Would you like to do? (o/s/q)
[s] > O
Schema file: schema.php generated

以上でマイグレーションファイルが作成されました。app/Config/Migration/ 以下に[タイムスタンプ]_add_projects_table.phpが作成されているはずです。内容は以下のような感じで、upの箇所がマイグレーションを行った歳に反映される変更内容、downの箇所がこのバージョンを取り消したときに変更される内容です(今回はテーブル追加なので戻す場合はdrop tableされます)

2. 自分でマイグレーションファイルを作る場合

次に空のマイグレーションファイルを自分で作る場合の説明をします。 まずいつものようにマイグレーションコマンドを実行します。今度は-fなしで大丈夫です。

./Console/cake Migrations.migration generate

実行すると、前回同様にschema.phpと比較をするかどうか尋ねられますので、今度は、nを選択します。

Do you want compare the schema.php file to the database? (y/n)

また前回と同様にプレビューを見るかどうか確認されますが、今回はひな形しか表示されないので特にみる必要はありません。最後にファイル名を入力します。今回は、先ほど作ったprojectsテーブルにdescriptionというカラムを追加することにするので、add_description_column_to_projects とでもします。これでファイルが生成されます。

今度は中身は以下のようになっていて、何の定義もない状態です。ここに適宜マイグレーションの定義を記述します。

public $migration = array(
    'up' => array(
    ),
    'down' => array(
    ),
);

どのような書き方をするかについては、https://github.com/CakeDC/migrationsを参照してください。

マイグレーションの実行

以上までで、マイグレーションの作成が終わったら、マイグレーションを適用します。

適用は以下のようなコマンドを実行します。

./Console/cake Migrations.migration run

実行すると、現在存在しているマイグレーションの一覧と適用済かどうかが表示されます。

Cake Migration Shell
---------------------------------------------------------------
Current migration version:
  #1352358031  1352358031_add_projects_table
---------------------------------------------------------------
Available migrations:
  [1351578012] 1351578012_initial_tables
        applied Tue, 30 Oct 2012 15:27:20 +0900
  [1352358031] 1352358031_add_projects_table
        applied Thu, 08 Nov 2012 16:00:31 +0900
  [1352358598] 1352358598_add_description_column_to_projects
        not applied
---------------------------------------------------------------
Please, choose what version you want to migrate to. [q]uit or [c]lean.
>

上記の例では、いま作った、add_description_column_to_projectsが未適用なので、その番号を入力します。 すると以下のように表示され、適用が完了します。

Please, choose what version you want to migrate to. [q]uit or [c]lean.
> 1352358598
---------------------------------------------------------------
Running migrations:
  [1352358598] 1352358598_add_description_column_to_projects
      > Adding field description to projects.

All migrations have completed.

なお、手動で作ったマイグレーションファイルの場合は、schema.phpは当然更新されていないので、マイグレーションの適用が終わったらschema.phpを更新しておくとよいでしょう。その場合は、何度も出てきた通り、./Console/cake schema generate -fを実行してください。

現在の適用状態がどうなっているかは以下のコマンドで確認できます。

./Console/cake Migrations.migration status

バージョンを下げる場合は、runコマンドで表示されたバージョンの中から戻すバージョンを確認し、番号を入力します。 また未適用のものが複数あったりしてまとめて適用したい場合は以下のようにします。非対話型で実行されるので、Jenkinsやデプロイスクリプトの組み込む場合はこれを利用します。

./Console/cake Migrations.migration run all -p

なお、マイグレーションの際にデータ移行やバックアップを行ったり初期データを登録したりしたい場合は、before() や after()の中にテーブルをごにょごにょする処理を実装することになります。

アジャイルコーチングやトレーニングを提供しています

株式会社アトラクタでは、アジャイル開発に取り組むチーム向けのコーチングや、認定スクラムマスター研修などの各種トレーニングを提供しています。ぜひお気軽にご相談ください。

詳細はこちら