Help us understand the problem. What is going on with this article?

Phinx導入ガイド

More than 1 year has passed since last update.

導入のための留意点

筆者は、CakePHP3での採用と他のフレームワークでも非依存で利用できるからという理由で導入をした。

しかしCakeDCのmigrations pluginと同じ考え方なんだろうという先入観があったために、かえって理解しづらい点があったので、そういう方は次の点を念頭に置くと悩みが少ない(かもしれない)。

  • 既にあるDBをリバースエンジニアリングする機能はない。
    • CakePHPのschema.phpに相当する概念がない。
  • DDLをSQLではなく、phpのコードで書けるのが利点…と捉えた方がいい。
    • マイグレーションをPhinxの管理下に置くということは、何もない状況からマイグレーションできるようにすべきだから、既存のDDLがある場合は書き換える必要がある。
    • SQLを書けるメソッド(executeやquery)があるので、ヒアドキュメントを使う方法はある。
  • 既にDBを構成している環境では使いにくい。
    • Phinxでは専用の履歴テーブル(デフォルトでPhinxlog)を作って、マイグレーションがどこまで適用しているかのステータスを保持する。
    • 既にDB展開済の場合は、Phinxが持つステータス状況と実態が合わずに、問題が起こりうる。
    • それを回避するには、マイグレーションのup/downメソッドにテーブルやフィールド(コラム)の実在確認の処理を書くか、初回を空っぽにして、2回目からまじめに書く。(ただしDDLは別提供)
    • または、初回マイグレーションだけぶっ放し、2回目からまじめに書く。

導入

既にリポジトリに入っており、利用者としてセットアップしたい人はインストールの項から参照のこと。

展開ディレクトリの作成

Composerを使うので、他のライブラリーをComposerでインストールしている場合は、同じvendorsに展開される。

もし独立した環境にしたい場合は、別にディレクトリを作り、その中で展開する。

gitignoreの設置

お好みでgitignoreを設置する。
composerでインストールできるものはリポジトリ管理に入れず、自分たちが書いたものだけを入れるというセオリーがあるので、全部をコミットするのは推奨しない。

$ vi .gitignore
vendor
Phinx.yml

composer

composer.jsonを配置

$ vi composer.json
{ 
    "require":{ 
        "robmorgan/Phinx": "*" 
    } 
} 

もし、チームで、環境にcomposerをインストールしない場合は、composer.pharをプロジェクトに配置してコミットしておく。

$ curl -s http://getcomposer.org/installer | php 

インストール

環境にcomposerをインストール済の場合は

$ composer install 

composerをインストールされていない場合は、composer.pharを使う。

$ php composer.phar install 

Phinxが使用できる状態になったので、環境定義(Phinx.yml)を生成し、DB情報を編集する。

$ ./vendor/bin/Phinx init
$ vi Phinx.yml

environmentsのところに、production, development, testingの3つの環境定義があるが、デフォルトはdevelopmentなので、複数の環境を使い分けない場合は、developmentのところだけ書き換える。

    development:
        adapter: mysql
        host: localhost
        name: (データベース名)
        user: (ログインID)
        pass: (パスワード)
        port: 3306
        charset: utf8

マイグレーション処理の流れ

詳細はそれぞれ後述ので、概要として流れを解説する。

  1. マイグレーション定義ファイルを生成する
    ファイルを作って、定義が書ける準備をする。

  2. マイグレーション定義ファイルに処理を書く。
    定義ファイルの中にchange, up, downのメソッドが生成されるので、これに記述を行う。

  3. マイグレーションを実行する。
    これによりDBに変更が実行され、Phinxlogテーブルが作成され、どこまでマイグレーションされているかを記録する。

以降、変更を加えるごとに1〜3を実行する。gitにおけるプル→コミットのように、3→1→2→3となる。
マイグレーションを反映させるには、3だけを実行する。

留意すべきは、リバースしないのでDBを直接編集せず、定義ファイルに記述し、それを実行することでDBに変更を与えること。

1.マイグレーション定義ファイルの生成

まず空の定義ファイルを作り、そこに処理を書いてマイグレーション定義が完成する。

次のコマンドで、定義ファイルが作成される。定義ファイルを格納するフォルダ(デフォルトでは ./migrations)が存在していない場合は、自動的に作成される。

$ ./vendor/bin/Phinx create (定義名)

定義名とは、マイグレーション定義ファイルに付ける名前であり、その中で定義されるクラス名になる。

公式ドキュメントでは「MyNewMigration」という名前になっているが、何をしたのか分かる名前を付ける方がよい。(statusを参照

定義名は、CamelCaseでなければならない。
「initial」はエラーになり、「Initial」はOK。

これで、./migrations/20150614151105_initial.php という日付+定義名でファイルが作成される。

ちなみに、この時点でPhinx.ymlを設定していなくてもエラーにならないことからも、マイグレーションの実行以外ではDBへのアクセスはない。

2.マイグレーションファイルに処理を書く

作成された定義ファイルを開く。

$ vi ./migrations/20150614151105_initial.php (例)

内容としては、change, up, downの3つのメソッドがあり、changeは最初コメントアウトされている(後述の通り、up/downと排他的に動作するため)。

メソッド 処理
up マイグレーションするときに実行される
down ロールバックするときに実行される
change マイグレーションするときに実行されるが、ロールバックする場合も、逆処理を行う。なお、このメソッドが有効(宣言されている状態)の場合、up/downは実行されない。

逆処理とは、addColumnの場合はremoveColumnが実行されることを意味する。当然全てが逆処理できるわけではなく、対応しているのは下記の通り。

changeメソッド内のコマンド(migrateで実行) rollbackで実行されるコマンド
createTable dropTable
renameTable renameTable(引数逆)
addColumn removeColumn
renameColumn renameColumn(引数逆)
addIndex removeIndex
addForeignKey dropForeignKey

これ以外の処理を行う場合は、up/downでそれぞれ処理を書く方がよい。

テーブル操作

$table = $this->table(テーブル名);

ここで代入した$tableに対して、処理を行う。

テーブルの追加

addColumnとコラム追加をしてから、create()メソッドを呼ぶ。
addColumnについては後述

$table->addColumn('name', 'string', array('limit' => 100)
      ->addColumn('age', 'integer')
      ->create();

create/updateとsave

createはテーブル生成を明示するものだが、公式ドキュメントではcreateではなく、saveメソッドを呼ぶと書かれている。
saveは、createまたはupdateになるので、基本的にup/downメソッドに記述する場合はsaveでよい。

しかしchangeメソッドで定義する場合は、公式ドキュメントにも書かれている通り、createまたはupdateを明示しなければならないと書かれている。理由はrollbackするときにコラムを消すのか、droptableするのかが自動的には判断できないため。
そのため、このドキュメントではcreate/updateを使用している。

テーブルの削除

$this->dropTable('users');

列操作

列の追加

$table->addColumn('列名', '型' , array(オプション))
      ->addColumn(…繰り返し…)
      ->save();

列名

フィールド名

型には次のものが使用できる。…と言いたいところだが、(お察し下さい)なので、公式ドキュメント参照。

なおstringは、limitオプションを付けない限り、デフォルトではvarchar(255)。

オプション

(お察し下さい)なので、公式ドキュメント参照。

列の削除

$table->removeColumn('列名')
      ->update()

列名の変更

$table->renameColumn('変更前', '変更後');

インデックス

addColumnなどと組み合わせて定義する。

$table->addIndex(array('列名1', '列名n'))
      ->update()

既にテーブルが存在しているかどうか

$exists = $this->hasTable('users');
if ($exists) {
     
}

SQLの実行

executeとqueryがあるが、返値に違いがある。

//影響を及ぼしたレコード数が返値
$count = $this->execute('DELETE FROM users');
//実行した結果が返値
$rows = $this->query('SELECT * FROM users');

既に作成済みのDDLをぶっ放す。

    public function up()
    {
        $query = <<<EOQ
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(255) default NULL,
  `age` integer,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`)
)AUTO_INCREMENT=1 ;
EOQ;
        $this->execute($query);
    }

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

idの自動生成を抑制する

Phinxは、id列を自動的に追加する。自分でid列の仕様を指定したり、primary keyを変更したい場合は邪魔になる。その場合は、下記のようにテーブル指定時にオプションで指定する。

$table = $this->table('statuses',
    [
        'id' => false,
        'primary_key' => ['id']
    ]);
$table->addColumn('id', 'char', ['limit' => 36])
      ->addColumn('name', 'char', ['limit' => 255])
      ->addColumn('model', 'string', ['limit' => 128])
      ->create();

出典

3.マイグレーションを実行する

migrate

マイグレーションの実行。マイグレーション定義ファイルのupメソッドまたはchangeメソッドを実行する。(changeメソッドがある場合は、upメソッドは無視される)
後述の-tオプションなしでは、最新まで一括でマイグレーションする。

$ ./vendor/bin/Phinx migrate

rollback

1つずつ戻す。downメソッドまたはchangeメソッドの逆処理を実行する。(up同様changeメソッドがある場合はdownメソッドは無視される。)

$ ./vendor/bin/Phinx rollback 

ターゲットを指定する

ターゲットを指定したい場合は、-tオプションを付け、マイグレーションIDを指定する。

例)20150614154730_my_migration.phpの場合

$ ./vendor/bin/Phinx migrate -t 20150614154730

status

全てのマイグレーション一覧を表示し、かつ現在のマイグレーション適用状況を表示する。

$ ./vendor/bin/Phinx status
 Status  Migration ID    Migration Name
-----------------------------------------
     up  20150614070924  InitialTable
     up  20150615021023  Users
   down  20150615111810  Logs
   down  20150615112743  Contents

この場合、Usersまでは適用されているが、Logsから適用されていないことを示している。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away