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

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

More than 3 years have 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機能により初期データ用ファイルを作成できる。
あとで追記予定。

ozawan
主にPHPやってます。 Rails, JavaScript勉強中。 スプラトゥーン廃人🦑 💥 🔫
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした