がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

phinxを使ってみた(マイグレーション変)

とりあえずinstall

composer require robmorgan/phinx

initで初期化をするらしい。

vendor/bin/phinx init

phinx.php が生えた。

<?php

return
[
    'paths' => [
        'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations',
        'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'
    ],
    'environments' => [
        'default_migration_table' => 'phinxlog',
        'default_environment' => 'development',
        'production' => [
            'adapter' => 'mysql',
            'host' => 'localhost',
            'name' => 'production_db',
            'user' => 'root',
            'pass' => '',
            'port' => '3306',
            'charset' => 'utf8',
        ],
        'development' => [
            'adapter' => 'mysql',
            'host' => 'localhost',
            'name' => 'development_db',
            'user' => 'root',
            'pass' => '',
            'port' => '3306',
            'charset' => 'utf8',
        ],
        'testing' => [
            'adapter' => 'mysql',
            'host' => 'localhost',
            'name' => 'testing_db',
            'user' => 'root',
            'pass' => '',
            'port' => '3306',
            'charset' => 'utf8',
        ]
    ],
    'version_order' => 'creation'
];

なるほど。
このフォーマットなら「他のFW(おいちゃんの想定はSlim)使ってて、そっちで(も)DBの接続設定がある」なんてケースでもちゃんとDRYに出来るねぇ!!
1点気になってたのが一瞬で氷塊したので、まぁ普通に「使う」前提でよいのではないかしらん???

見るに
・いったんのデフォはdevelopment
っぽいので、そのままテスト用のDBの設定をdevelopmentに書いて、追加で実験してみませう。

お次。
必要なディレクトリを作るぽ。

mkdir -p db/migrations db/seeds

これはまぁ実際には「このディレクトリもgitに登録しておく」とかで良さそうざます。
&
configの設定の「%%PHINX_CONFIG_DIR%%」がちょい気になるが、まぁなんかあったら後で出てくるでせう。
次。

眼目になるマイグレーションファイル作成。
本家サイトとか、アッパーキャメルなのがちょいと気になるなぁ……いったんヘビにしてみよう。

php vendor/bin/phinx create table_name

The migration class name "table_name" is invalid. Please use CamelCase format.

わをwww
キャメル固定なのかwww

では改めて。

php vendor/bin/phinx create TableName

Phinx by CakePHP - https://phinx.org.

using config file phinx.php
using config parser php
using migration paths
- /home/furu/PhinxTest/db/migrations
using seed paths
- /home/furu/PhinxTest/db/seeds
using migration base class Phinx\Migration\AbstractMigration
using default template
created db/migrations/20230819124347_table_name.php

ほむ……seedとmigrationsにファイルが出来てる? 確認。

seedには……ない。
なんじゃろ???
(後で分かった。ここ。seederを作る所なんだ)

migrationsにはファイルが出来てる。

<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class TableName extends AbstractMigration
{
    /**
     * Change Method.
     *
     * Write your reversible migrations using this method.
     *
     * More information on writing migrations is available here:
     * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
     *
     * Remember to call "create()" or "update()" and NOT "save()" when working
     * with the Table class.
     */
    public function change(): void
    {

    }
}

簡素だなをいw
んで、指定したのは純粋に「クラス名」なのか。それ以外の処理、なんもないw

(RDB準備中...RDB準備中...)

軽く書いていこう。
書く場所は
・change() に書くと、(ある程度までは)マイグレーションを巻き戻す時、勝手に良い感じに巻き戻してくれる
・でなきゃ、おとなしく up() と donw() を書け
らしい。

で……ちょっと気になる記述も見かけたので、その辺の確認込みで、いくつか書いてみる。

    public function change(): void
    {
        $table = $this->table('test');
        $table->addColumn('name', 'string')
            ->addColumn('str', 'varchar', ['limit' => 128])
            ->addColumn('str2', 'varbinary', ['limit' => 128])
            ->addColumn('num', 'int', ['comment' => 'コメント'])
            ->addColumn('num2', 'bigint')
            ->addColumn('created_at', 'datetime')
            ->create();

    }

ドライランがあるとの事で、早速やってみる。
あと、 -e での環境指定を「あえて」省略してみる(configにデフォ値あったし)。

php vendor/bin/phinx migrate --dry-run

InvalidArgumentException: An invalid column type "varchar" was specified for column "str".

あそ。
他いくつか修正。

    public function change(): void
    {
        $table = $this->table('test');
        $table->addColumn('name', 'string')
            ->addColumn('str', 'string', ['limit' => 128])
            ->addColumn('str2', 'varbinary', ['limit' => 128])
            ->addColumn('num', 'integer', ['comment' => 'コメント'])
            ->addColumn('num2', 'biginteger')
            ->addColumn('created_at', 'datetime')
            ->create();

    }

CREATE TABLE `test` (
`id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL,
`str` VARCHAR(128) NULL,
`str2` VARBINARY(128) NULL,
`num` INT(11) NULL COMMENT 'コメント',
`num2` BIGINT(20) NULL,
`created_at` DATETIME NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

あら?
うん前情報通り「勝手にID入れてくる」のは気になるが、VARBINARYに対応しているのはおいちゃん的に大分と高ポイントざますよ?
ほむ……ちょいと本気を出してみよう(実験用なんでテーブルレイアウトはきにすんな)。

    public function change(): void
    {
        $table = $this->table('test', [
            'id' => false,
            'primary_key' => 'test_id',
            'comment' => 'テーブルコメント',
        ]);
        $table
            ->addColumn('test_id', 'biginteger', ['null' => false, 'signed' => false, 'identity' => true,])
            ->addColumn('name', 'string')
            ->addColumn('str', 'string', ['limit' => 128, 'null' => false])
            ->addColumn('str2', 'varbinary', ['limit' => 128])
            ->addColumn('num', 'integer', ['comment' => 'コメント'])
            ->addColumn('num2', 'biginteger')
            ->addColumn('created_at', 'datetime', ['null' => false, 'default' => 'CURRENT_TIMESTAMP'])
            ->create();

        //
        $table = $this->table('test_2', [
            'id' => false,
            'primary_key' => ['test_id', 'str'],
            'comment' => 'テーブルコメント',
        ]);
        $table
            ->addColumn('test_id', 'biginteger', ['null' => false, 'signed' => false, 'identity' => true,])
            ->addColumn('str', 'string', ['limit' => 128, 'null' => false])
            ->create();
    }

CREATE TABLE `test` (
`test_id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL,
`str` VARCHAR(128) NOT NULL,
`str2` VARBINARY(128) NULL,
`num` INT(11) NULL COMMENT 'コメント',
`num2` BIGINT(20) NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`test_id`)
) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='テーブルコメント';

CREATE TABLE `test_2` (
`test_id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
`str` VARCHAR(128) NOT NULL,
PRIMARY KEY (`test_id`,`str`)
) ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='テーブルコメント';

よし、よし。
ちょっと調べるのに時間がかかったけど、大体いけるっぽいなぁ。
よしちゃんと実行してみやう。

php vendor/bin/phinx migrate
mysql> show tables;
+----------------------+
| Tables_in_phinx_test |
+----------------------+
| phinxlog             |
| test                 |
| test_2               |
+----------------------+
3 rows in set (0.00 sec)

mysql> show create table test \G
*************************** 1. row ***************************
       Table: test
Create Table: CREATE TABLE `test` (
  `test_id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `str` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
  `str2` varbinary(128) DEFAULT NULL,
  `num` int DEFAULT NULL COMMENT 'コメント',
  `num2` bigint DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`test_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='テーブルコメント'
1 row in set (0.00 sec)

mysql> show create table test_2 \G
*************************** 1. row ***************************
       Table: test_2
Create Table: CREATE TABLE `test_2` (
  `test_id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `str` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`test_id`,`str`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='テーブルコメント'
1 row in set (0.00 sec)

んむんむ、よきよき。
一応、rollback

php vendor/bin/phinx rollback
mysql> show tables;
+----------------------+
| Tables_in_phinx_test |
+----------------------+
| phinxlog             |
+----------------------+
1 row in set (0.01 sec)

よきよき。

一応メモ程度に残しておくと。

php vendor/bin/phinx migrate -e 環境名
php vendor/bin/phinx rollback -e 環境名

ってのが本来っぽい感じではあるので、一応。
ただまぁこれだと

・ステージングまでは普通に「コードupしてからマイグレーションする」
・本番は「先にマイグレーションしてからコードupする」

とかもできそうだなぁ……ちょいと運用も考えてみやう。

大雑把に
・「テーブル作る」とか「カラム追加する」くらいなら、change() に実装すればよさげ
・一応「SQLダイレクト発行」もある、みたいだけど、現状だとあんまりいらなさそうな雰囲気がある
・まぁ必要になったら「up()とdown()で実装しつつSQL書く」でよいんじゃなかろうか
って感じなので。
「便利な機能はあるけど簡単にoffれるから足かせにならないので気楽」って感じだなぁ。
うん、ちょいと使い込んでみてもよいかも。ちょっと癖があるから色々調べなきゃいかんけどw

次回はseederを確認してみませう。