cakephp3

CakePHP3のマイグレーションまとめ

More than 1 year has passed since last update.

CakePHP3のマイグレーションについて調べたので備忘録。(色んな記事の寄せ集めという感じ:sunglasses:)

概要

  • CakePHP3ではマイグレーションツール Phinx を採用している (Cakeのコマンドはラッパー)
  • コマンドが2種類ある (bin/cake migrationsbin/cake bake migration)
  • /bin/cake コマンドは php /bin/cake.php でもOK
  • マイグレーションファイルは config/Migration/ 以下に作成される
  • ファイル名は、作成日時(YYYYMMDDHHMMSS)_マイグレーション名.php
  • 明示的にオプション指定しない限り、defaultのデータベース設定を使用する
  • migrationコマンドを実行すると、データベースにphinxlogテーブルを作成し、このテーブルで実行履歴を管理する
MariaDB > select * from phinxlog;
+----------------+----------------+---------------------+---------------------+------------+
| version        | migration_name | start_time          | end_time            | breakpoint |
+----------------+----------------+---------------------+---------------------+------------+
| 20170525090543 | Initial        | 2017-05-25 09:05:43 | 2017-05-25 09:05:43 |          0 |
| 20170525090709 | CreateProducts | 2017-05-25 09:27:41 | 2017-05-25 09:27:41 |          0 |
+----------------+----------------+---------------------+---------------------+------------+

マイグレーション適用状況を確認

コマンド
bin/cake migrations status

↓結果はこんな感じ

結果
 Status  Migration ID    Migration Name 
-----------------------------------------
     up  20170525090543  Initial 
   down  20170525090709  CreateProducts 
  • up = 実行済み
  • down = 未実行

現在のDBからマイグレーションファイルを作成

https://book.cakephp.org/3.0/ja/migrations.html#id14

コマンド
bin/cake bake migration_snapshot Initial
  • config/Migration/YYYYMMDDHHMMSS_Initial.php がファイルが作成される
  • config/Migrations/schema-dump-default.lock がファイルが作成(更新)される
  • スキーマのみで、データ部分は作成されない (データはseed機能で入れる)
  • Initialはマイグレーション名なので他の名前でもOK
  • migrations statusは実行済みになる
  • 作成したファイルをmigrationコマンドでリストアしても同じ定義には戻らなかった(MySQL/MariaDBの場合)
    • tinyint(x)が、int(x)に変わっている
      • tinyint(1)の場合、恐らくCakePHP内部で、booleanをtinyint(1)として扱っているのでint(x)にならない
      • tinyintを指定したい場合、MySQL用アダプタを使用して書き直す必要あり?
    • インデックス, ユニークキー, 外部キーの名前が少し変わっている

マイグレーションファイルを作成

https://book.cakephp.org/3.0/ja/migrations.html#id3

作成方法は2通り。

作成方法によって、マイグレーションファイル冒頭のuse宣言が異なる (内部的にはほぼ同じっぽい)

パターン1 bin/cake bake migration マイグレーション名 で作成 (お手軽版)

シンタックス

bin/cake bake migration マイグレーション名 カラム定義

命名パターン 処理内容
(/^(Create)(.*)/) 指定したテーブルを作成
(/^(Drop)(.*)/) 指定したテーブルを削除
(/^(Add).(?:To)(.)/) 指定したテーブルにカラム追加
(/^(Remove).(?:From)(.)/) 指定のテーブルのカラムを削除
(/^(Alter)(.*)/) 指定したテーブルを変更 (CreateTable と AddFieldの別名)

例) テーブル作成

コマンド
bin/cake bake migration CreateProducts name:string description:text created modified
  • config/Migration/YYYYMMDDHHMMSS_CreateProducts.php が作成される
  • change()メソッド内にaddColumn()とcreate()が記述されている
<?php
use Migrations\AbstractMigration;

class CreateProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this->table('products');
        $table->addColumn('name', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ]);
        $table->addColumn('description', 'text', [
            'default' => null,
            'null' => false,
        ]);
        $table->addColumn('created', 'datetime', [
            'default' => null,
            'null' => false,
        ]);
        $table->addColumn('modified', 'datetime', [
            'default' => null,
            'null' => false,
        ]);
        $table->create();
    }
}

例) カラム追加

コマンド
bin/cake bake migration AddPriceToProducts price:decimal
  • config/Migration/YYYYMMDDHHMMSS_AddPriceToProducts.php が作成される
  • change()メソッド内にaddColumn()とupdate()が記述されている
<?php
use Migrations\AbstractMigration;

class AddPriceToProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this->table('products');
        $table->addColumn('price', 'decimal', [
            'default' => null,
            'null' => false,
        ]);
        $table->update();
    }
}

例) カラム削除

コマンド
bin/cake bake migration RemovePriceFromProducts price
  • config/Migration/YYYYMMDDHHMMSS_RemovePriceFromProducts.php が作成される
  • change()メソッド内にremoveColumn()とupdate()が記述されている
<?php
use Migrations\AbstractMigration;

class RemovePriceFromProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this->table('products');
        $table->removeColumn('price');
        $table->update();
    }
}

例) テーブル削除

コマンド
bin/cake bake migration DropProducts
  • config/Migration/YYYYMMDDHHMMSS_DropProducts.php が作成される
  • change()メソッド内にdrop()が記述されている
<?php
use Migrations\AbstractMigration;

class DropProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this->table('products');
        $table->drop();
    }
}

パターン2 bin/cake migrations create マイグレーション名 で作成 (カスタム定義用)

例)

コマンド
bin/cake migrations create CreateProducts
  • config/Migration/YYYYMMDDHHMMSS_create_products.php が作成される
  • 何も処理が記述されていないので、1から処理を記述する
  • 引数のマイグレーション名はキャメルケースにしないとエラーになる
<?php

use Phinx\Migration\AbstractMigration;

class CreateProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * Write your reversible migrations using this method.
     *
     * More information on writing migrations is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
     *
     * The following commands can be used in this method and Phinx will
     * automatically reverse them when rolling back:
     *
     *    createTable
     *    renameTable
     *    addColumn
     *    renameColumn
     *    addIndex
     *    addForeignKey
     *
     * Remember to call "create()" or "update()" and NOT "save()" when working
     * with the Table class.
     */
    public function change()
    {
      // https://book.cakephp.org/3.0/ja/migrations.html や
            // http://docs.phinx.org/en/latest/migrations.html を参考に処理を書く
    }
}

マイグレーションファイルのメソッドについて

以下のメソッドが使用可能

 
※ change()指定時は、up()やdown()を書いても無視される
※ なので、change()のみを書いたファイルか、up()/down()を書いたファイルを作成する

Phinxで利用可能なフィールドの型

https://book.cakephp.org/3.0/ja/migrations.html#id8

  • string
  • text
  • integer
  • biginteger
  • float
  • decimal
  • datetime
  • timestamp
  • time
  • date
  • binary
  • boolean
  • uuid

RDBMS固有の型、MySQLのtinyint等を指定したい場合、以下のアダプタを使用する

マイグレーション実行

https://book.cakephp.org/3.0/ja/migrations.html#migrate

最新まで実行

コマンド
bin/cake migrations migrate

指定したマイグレーションIDまで実行

コマンド
bin/cake migrations migrate -t マイグレーションID

ロールバック

https://book.cakephp.org/3.0/ja/migrations.html#rollback

1つ前に戻す

コマンド
bin/cake migrations rollback

指定したマイグレーションIDまで戻す

コマンド
bin/cake migrations rollback -t マイグレーションID

マイグレーションを実行済みにする(DBには反映しない)

https://book.cakephp.org/3.0/ja/migrations.html#mark-migrated

すべて実行済みにする

コマンド
bin/cake migrations mark_migrated

指定したマイグレーションIDだけマイグレーション済みにする

コマンド
bin/cake migrations mark_migrated --target=マイグレーションID --only

直接DBの方を変更済みの時などで、マイグレーションを実行したくない場合に、実行済みに出来る。

実行前

migrations status
 Status  Migration ID    Migration Name 
-----------------------------------------
     up  20170525090543  Initial 
   down  20170525090709  CreateProducts 
phinxlogテーブル
MariaDB > select * from phinxlog;
+----------------+----------------+---------------------+---------------------+------------+
| version        | migration_name | start_time          | end_time            | breakpoint |
+----------------+----------------+---------------------+---------------------+------------+
| 20170525090543 | Initial        | 2017-05-25 09:05:43 | 2017-05-25 09:05:43 |          0 |
+----------------+----------------+---------------------+---------------------+------------+

という状況で、コマンドを実行すると

コマンド
bin/cake migrations mark_migrated

以下のようになる (productsテーブルは作成されていない)

実行後

migrations status
 Status  Migration ID    Migration Name 
-----------------------------------------
     up  20170525090543  Initial        
     up  20170525090709  CreateProducts 
phinxlogテーブル
MariaDB > select * from phinxlog;
+----------------+----------------+---------------------+---------------------+------------+
| version        | migration_name | start_time          | end_time            | breakpoint |
+----------------+----------------+---------------------+---------------------+------------+
| 20170525090543 | Initial        | 2017-05-25 09:05:43 | 2017-05-25 09:05:43 |          0 |
| 20170525090709 | CreateProducts | 2017-05-25 09:27:41 | 2017-05-25 09:27:41 |          0 |
+----------------+----------------+---------------------+---------------------+------------+

差分算出用ダンプファイルのみ作成

https://book.cakephp.org/3.0/ja/migrations.html#dump-bake

コマンド
bin/cake migrations dump
  • config/Migrations/schema-dump-default.lock がファイルが作成(更新)される
  • その時点のDB情報が保存されている
  • ダンプファイルは、migrate / rollback / スナップショット実行時にも作成される
  • このコマンドで作成したダンプファイルでは、うまく差分算出できなかった

現在のDB状態とダンプファイルの差分からマイグレーションファイルを作成

https://book.cakephp.org/3.0/ja/migrations.html#id15

コマンド
bin/cake bake migration_diff NameOfTheMigrations
  • config/Migration/YYYYMMDDHHMMSS_NameOfTheMigrations.php が作成される
  • 前回のダンプファイル(schema-dump-default.lock)更新以降に追加・削除されたスキーマのマイグレーション処理が書かれている
    • migrations dumpで作成したダンプファイルでは、差分がうまく出力されなかった(全スキーマのcreate文が出力された)
    • migration_snapshot / migrations migrate で作成したダンプファイルでは問題なく差分のみ出力された
  • config/Migrations/schema-dump-default.lock がファイルが作成(更新)される

初期データの作成

https://book.cakephp.org/3.0/ja/migrations.html#seed

Phinxのseed機能により初期データ用ファイルを作成できる。
あとで追記予定。