2022-05-19に投稿

(PHP) Phoenix でデータ関係が依存しているDBをマイグレーションする

lulco/phoenix でデータ関係が依存しているDBをマイグレーションする方法をメモ。

ドキュメントが全然ないので地道にやっていきます……。

コード

早速コードを。

phoenix.php

return [
    'migration_dirs' => [
        'first'  => __DIR__ . '/migrations/first',
        'second'  => __DIR__ . '/migrations/second',
    ],
    'environments' => [
        'local'      => [
            'adapter'  => 'mysql',
            'host'     => $_ENV['MYSQL_HOST'],
            'port'     => (int)$_ENV['MYSQL_PORT'], // optional
            'username' => $_ENV['MYSQL_USER'],
            'password' => $_ENV['MYSQL_PASSWORD'],
            'db_name'  => $_ENV['MYSQL_DBNAME'],
            'charset'  => 'utf8mb4',
        ],
        'production' => [
            'adapter'  => 'mysql',
            'host'     => $_ENV['MYSQL_HOST'],
            'port'     => (int)$_ENV['MYSQL_PORT'], // optional
            'username' => $_ENV['MYSQL_USER'],
            'password' => $_ENV['MYSQL_PASSWORD'],
            'db_name'  => $_ENV['MYSQL_DBNAME'],
            'charset'  => 'utf8mb4',
        ],
    ],
    'default_environment' => 'local',
    'log_table_name'      => 'phoenix_log',
];

肝は migration_dirsfirstsecond でそれぞれ対応するディレクトリを指定しているところ。

/migrations/first/hoge.php

<?php

namespace migrations;

use Phoenix\Database\Element\Index;
use Phoenix\Migration\AbstractMigration;

class HogeMigration extends AbstractMigration
{
    protected function up(): void
    {
        $this->table('hoge')
             ->addColumn('create_date', 'datetime')
             ->addColumn('name', 'string')
             ->create();

        // insert
        $hogeData = [
            [
                'name' => 'foo'
            ],
            [
                'name' => 'bar'
            ],
            [
                'name' => 'buz'
            ],
            // 略
        ];
        $rows = [];
        foreach ($hogeData as $key => $val) {
            $rows[] = [
                'create_date' => date('Y-m-d H:i:s'),
                'name' => $val['name'],
            ];
        }
        $this->insert('hoge', $rows);
    }

    protected function down(): void
    {
        $this->table('hoge')
             ->drop();
    }
}

まずは最初に hoge というDBを作成し、そこにデータを流し込みます。

/migrations/second/fuga.php

<?php

namespace migrations;

use Phoenix\Database\Element\Index;
use Phoenix\Migration\AbstractMigration;

class FugaMigration extends AbstractMigration
{
    protected function up(): void
    {
        $this->table('fuga')
             ->addColumn('create_date', 'datetime')
             ->addColumn('name', 'string')
             ->addColumn('hoge_id', 'integer')
             ->create();

        // select hoge data
        $hogeRows = $this->select('SELECT id, name FROM hoge');
        // insert
        $fugaData = [
            [
                'name' => 'un'
            ],
            [
                'name' => 'deux'
            ],
            [
                'name' => 'trois'
            ],
            // 略
        ];
        $rows = [];
        foreach ($fugaData as $key => $val) {
            $id = 0;
            // hoge の name と fuga の name が一致する要素を array_filter() で抽出し、 array_values() で番号を詰める
            $hogeArray = array_values(
                array_filter(
                    $hogeRows,
                    function($hogeRow) use ($val) {
                        $needle = mb_strlen(mb_strtolower($val[0])) > 0 ? mb_strtolower($val[0]) : 'NOTHING';
                        return mb_strpos(mb_strtolower($hogeRow['name']), $needle) !== false;
                    }
                )
            );
            // $hogeArray の要素が1つ (一意に定まる) 場合はその値を、そうでない場合はデフォルト値をセット
            $id = count($hogeArray) === 1 ? (int)$hogeArray[0]['id'] : 0;
            $rows[] = [
                'create_date' => date('Y-m-d H:i:s'),
                'name' => $val[0],
                'hoge_id' => $id, // 上述でセットした id を使用
            ];
        }
        $this->insert('fuga', $rows);
    }

    protected function down(): void
    {
        $this->table('fuga')
             ->drop();
    }
}

次に fuga を作成し、そこに徐に $this->select() で SQL文 を発行、先程流し込んだデータを抽出します。

その抽出したデータと fuga に流し込みたいデータを突き合わせて初期データを生成し、それを fuga に流し込む……という算段。

これで意図したデータをマイグレーションすることができました。

参考

ドキュメントがないのでコードを読んで普通に select とか使えそう、と思って試したりしていました。

Originally published at labor.ewigleere.net
ツイッターでシェア
みんなに共有、忘れないようにメモ

arm-band

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント