ダッシュで奪取

自分用のメモ

【Phalcon】マイグレーション色々

目次

  1. マイグレーションファイル作成
  2. マイグレーションファイルの中身
  3. テーブルを作成したい
  4. テーブルを削除したい
  5. 外部キーを追加したい
  6. マイグレーション実行
  7. マイグレーション実行時に、テストデータを投入したい
  8. 参考URL

マイグレーション機能を持っていることは分かったのですが、日本語の資料が…あまりにも無い…!あっても古い…!と困ったのでメモです。
やりたいことはできたのでOKとしてしまいましたが、やり方が合っているのか分かりません…

作業環境
  • MySQL:8.0.18
  • Phalcon:3.4.5
この記事の目標
  • マイグレーションコマンドで、バージョンのup、downができる

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

$ phalcon migration generate
  • app/migrations以下に、マイグレーション用のディレクトリが作成される
  • デフォルトでは1.0.0 → 1.0.1 → 1.0.2 ...のような感じでバージョン管理される
  • 各バージョンのディレクトリ内に、テーブルごとのファイルを作成する
こんな感じ
app/
┗ migrations/
    ┗ 1.0.0/
        ┣ employees.php
        ┗ departments.php

2. マイグレーションファイルの中身

app/migrations/1.0.0/employees.php
<?php 
use Phalcon\Db\Column;
use Phalcon\Db\Index;
use Phalcon\Db\Reference;
use Phalcon\Mvc\Model\Migration;

class EmployeesMigration_100 extends Migration
{
    public function morph()
    {
    }

    public function up()
    {
    }

    public function down()
    {
    }
}
  • クラス名は「[テーブル名]Migration_[バージョン名]」

    • Employeesテーブルのバージョン1.0.0「EmployeesMigration_100」
  • マイグレーション時の処理はupに書く

  • ロールバック時の処理はdownに書く
  • morphはよく分からなかったので、分かり次第追記

  • テーブルがあれば、中身が自動で書き込まれる(完全ではないので、自分で修正する必要がある)

  • テーブルに手動で項目追加したり制約追加したり → コマンドを打ってマイグレーションファイル作成、という流れ?

3. テーブルを作成したい

下記表のテーブルを作成するマイグレーションファイルを書く

Employees
カラム名 備考
id int(10) notnull, primary
name varchar(50) notnull
department_id int(10) notnull
created_at datetime notnull
updated_at timestamp notnull
app/migrations/1.0.0/employees.php
<?php 
use Phalcon\Db\Column;
use Phalcon\Db\Index;
use Phalcon\Db\Reference;
use Phalcon\Mvc\Model\Migration;

class EmployeesMigration_100 extends Migration
{
    public function morph()
    {
    }

    public function up()
    {
        $this->morphTable('employees', [
            'columns' => [
                new Column('id', [
                    'type'          => Column::TYPE_INTEGER,
                    'size'          => 10,
                    'notNull'       => true,
                    'autoIncrement' => true,
                    'primary'       => true,
                    'first'         => true,
                ]),
                new Column('name', [
                    'type'          => Column::TYPE_VARCHAR,
                    'size'          => 50,
                    'notNull'       => true,
                    'after'         => 'id',
                ]),
                new Column('department_id', [
                    'type'          => Column::TYPE_INTEGER,
                    'size'          => 10,
                    'notNull'       => true,
                    'after'         => 'name',
                ]),
                new Column('created_at', [
                    'type'          => Column::TYPE_DATETIME,
                    'notNull'       => true,
                    'size'          => 1,
                    'after'         => 'department_id',
                ]),
                new Column('updated_at', [
                    'type'          => Column::TYPE_TIMESTAMP,
                    'notNull'       => true,
                    'size'          => 1,
                    'after'         => 'created_at',
                ]),
            ],
            'indexes' => [
                new Index('PRIMARY', ['id'], 'PRIMARY')
            ],
            'options' => [
                'TABLE_TYPE'      => 'BASE TABLE',
                'AUTO_INCREMENT'  => '1',
                'ENGINE'          => 'InnoDB',
                'TABLE_COLLATION' => 'utf8_general_ci'
            ],
        ]);
    }

    public function down()
    {
    }
}
  • 1.0.0(最初のバージョン)なので、downの記述は不要

  • firstafter

    • カラムの順番を設定
  • 他に指定できる型

    • TYPE_TEXT、TYPE_LONGTEXT、TYPE_BOOLEAN等

4. テーブルを削除したい

  • 1.0.1で新しくtestテーブルを作成した場合、down側に「testテーブルを削除する処理」が必要
    • 1.0.1 upでテーブル作成、downでテーブル削除が走るようにする
app/migrations/1.0.1/test.php
<?php
use Phalcon\Db\Column;
use Phalcon\Db\Index;
use Phalcon\Db\Reference;
use Phalcon\Mvc\Model\Migration;

class TestMigration_101 extends Migration
{
    public function __construct() {
        $this->connect = self::$_connection;
    }

    public function up()
    {
        // 省略:testテーブルを作成する記述
    }
    public function down()
    {
        $this->connect->dropTable('test');
    }

5. 外部キーを追加したい

  • 「employeesテーブル」の、「department_id」に外部キー制約を追加する

    • employees.department_id = departments.idとする
app/migrations/1.0.0/employees.php
<?php 
use Phalcon\Db\Column;
use Phalcon\Db\Index;
use Phalcon\Db\Reference;
use Phalcon\Mvc\Model\Migration;

class EmployeesMigration_101 extends Migration
{
    function __construct() {
        $this->connect = self::$_connection;
    }

    public function morph()
    {
    }

    public function up()
    {
        $this->morphTable('employees', [
            'columns' => [
                // 省略:各カラム設定の記述
            ],
            'indexes' => [
                new Index('PRIMARY', ['id'], 'PRIMARY'),
                new Index('fk_department_id', ['department_id'], null)
            ],
            'references' => [
                new Reference('fk_department_id', [
                    'referencedTable'   => 'departments',
                    'columns'           => ['department_id'],
                    'referencedColumns' => ['id'],
                    'onUpdate'          => 'NO ACTION',
                    'onDelete'          => 'NO ACTION'
                ])
            ],
            'options' => [
                'TABLE_TYPE'      => 'BASE TABLE',
                'AUTO_INCREMENT'  => '4',
                'ENGINE'          => 'InnoDB',
                'TABLE_COLLATION' => 'utf8_general_ci'
            ],
        ]);
    }

    public function down()
    {
        $table_name  = 'employees';
        $schema_name = 'phalcon-crud'; // DB名
        $index_name  = 'fk_department_id';

        $this->connect->dropForeignKey($table_name, $schema_name, $index_name);
        $this->connect->dropIndex($table_name, $schema_name, $index_name);
    }
}

外部キーの追加

  • 23行目〜:「fk_department_id」という名前で、department_idにインデックスを張る
// 23:
'indexes' => [
    new Index('PRIMARY', ['id'], 'PRIMARY'),
    new Index('fk_department_id', ['department_id'], null)
],
  • 27行目〜:「fk_department_id」に外部キー制約を設定する
// 27:
'references' => [
    new Reference('fk_department_id', [
        'referencedTable'   => 'departments',
        'columns'           => ['department_id'],
        'referencedColumns' => ['id'],
        'onUpdate'          => 'NO ACTION',
        'onDelete'          => 'NO ACTION'
    ])
],

外部キーの削除

  • 今回のバージョンで新しくインデックス・外部キーを設定したので、down側に削除処理を書く必要がある

  • 45行目〜:外部キー削除してから → インデックス削除

// 45:
public function down()
{
    $table_name  = 'employees';
    $schema_name = 'phalcon-crud'; // DB名
    $index_name  = 'fk_department_id';

    $this->connect->dropForeignKey($table_name, $schema_name, $index_name);
    $this->connect->dropIndex($table_name, $schema_name, $index_name);
}

6. マイグレーション実行

  • 初回実行時、バージョン管理用のファイル .phalcon/migration-versionが作成される

  • up及びdown処理を実行することで、上記ファイルに現在のバージョンが書き込まれていく

up

$ phalcon migration run

down

$ phalcon migration run --version=[戻したいバージョン]

# バージョン1.0.0に戻す
$ phalcon migration run --version=1.0.0

7. マイグレーション実行時に、テストデータを投入したい

up実行時、3件データを作成するサンプル

app/migrations/1.0.0/employees.php

全体

<?php 
use Phalcon\Db\Column;
use Phalcon\Db\Index;
use Phalcon\Db\Reference;
use Phalcon\Mvc\Model\Migration;
use Phalcon\Db\RawValue; // 日付作成に使用

class EmployeesMigration_100 extends Migration
{
    function __construct() {
        $this->connect = self::$_connection;
    }

    public function morph()
    {
    }

    public function up()
    {
        $this->morphTable('employees', [
            'columns' => [
                // 省略:各カラム設定の記述
            ],
            'indexes' => [
                new Index('PRIMARY', ['id'], 'PRIMARY')
            ],
            'options' => [
                'TABLE_TYPE'      => 'BASE TABLE',
                'AUTO_INCREMENT'  => '1',
                'ENGINE'          => 'InnoDB',
                'TABLE_COLLATION' => 'utf8_general_ci'
            ],
        ]);

        // 初期データ投入
        $this->insert_employees();
    }

    public function down()
    {
    }

    // 初期データ投入
    private function insert_employees()
    {
        $table_name   = 'employees';
        $current_date = new RawValue("now()");
        $this->connect->insertAsDict(
            $table_name, [
                'name'          => '開発太郎',
                'department_id' => 1,
                'created_at'    => $current_date,
                'updated_at'    => $current_date,
            ]
        );
        $this->connect->insertAsDict(
            $table_name, [
                'name'          => '営業太郎',
                'department_id' => 2,
                'created_at'    => $current_date,
                'updated_at'    => $current_date,
            ]
        );
        $this->connect->insertAsDict(
            $table_name, [
                'name'          => '総務花子',
                'department_id' => 3,
                'created_at'    => $current_date,
                'updated_at'    => $current_date,
            ]
        );
    }
}
  • 6行目〜:日付作成で使用するクラスを指定
// 6:
use Phalcon\Db\RawValue; // 日付作成に使用
  • 10行目〜:INSERT処理のために、DB接続設定を取得しておく
// 10:
function __construct() {
    $this->connect = self::$_connection;
}
  • 35行目〜:up処理の最後で、初期データ投入処理を呼ぶ
// 35:
// 初期データ投入
$this->insert_employees();
  • 43行目〜:初期データ投入処理
// 43:
// 初期データ投入
private function insert_employees()
{
    $table_name   = 'employees';
    $current_date = new RawValue("now()");
    $this->connect->insertAsDict(
        $table_name, [
            'name'          => '開発太郎',
            'department_id' => 1,
            'created_at'    => $current_date,
            'updated_at'    => $current_date,
        ]
    );
    $this->connect->insertAsDict(
        $table_name, [
            'name'          => '営業太郎',
            'department_id' => 2,
            'created_at'    => $current_date,
            'updated_at'    => $current_date,
        ]
    );
    $this->connect->insertAsDict(
        $table_name, [
            'name'          => '総務花子',
            'department_id' => 3,
            'created_at'    => $current_date,
            'updated_at'    => $current_date,
        ]
    );
}

8. 参考URL