Featured image of post BEAR.SundayでDoctrine Migrationsを使ってみよう

BEAR.SundayでDoctrine Migrationsを使ってみよう

Twitter ツイート Hatena Bookmark ブックマーク

最近はHTTP Cacheまわりにかなり興味がでてきたので、久しぶりにBEAR.Sundayを触っています。
全く持って覚えてなかったので、素振りをしようと思ってとりあえずチケットチュートリアルをやりました。

無事に素振りが終わって実際に趣味のアプリケーションのコードを書き始めようと思いましたが、データベースのマイグレーションツールをどうしようか悩みました。

チケットチュートリアルでは、データベースのマイグレーションにphinxを使っています。
特にphinxに不満はありませんが、なんとなく他になに違うツールはないかと調べてみました。

Doctrine MigrationsはDoctrineを利用していなくても使える

調べていくうちに、Doctrine MigrationsがDoctrineを利用していなくても使えることが書かれたzennの記事に遭遇しました。

PHPで「Doctrine Migrations」を使ってみる

本当に素晴らしい記事ですね!Symfonyユーザーの自分はDoctrine MigrationsがDoctrineを利用していなくても使えるなんて知りませんでした。
(普段からSymfony + Doctrineで開発しているから逆に気づかないやつですね。)

というとでBEAR.SundayでDoctrine Migrationsを使うことにしました。

まずはBEAR.Sundayでプロジェクトを作る

まずはBEAR.Sundayでプロジェクトを作ります。

1
$ composer create-project bear/skeleton Polidog.DoctrineMigrationExample

Doctrine Migrationsのパッケージをインストールする

次にDoctrine Migrationのパッケージをインストールします。

1
$ composer req --dev doctrine/migrations

データベースをdocker composeで用意する

compose.yamlを用意します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  database:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: example_db
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
    ports:
        - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
    mysql_data:

用意できたらコンテナを起動しておきます。

1
2
$ docker compose up -d
 ✔ Container polidogdoctrinemigrationexample-database-1  Started   

問題なく起動できるかと思います。

envファイルについて

データベース接続情報を管理するのにDotenvを使います。

1
2
3
4
5
6
7
DB_NAME=example_db
DB_USER=root
DB_PASSWORD=root
DB_HOST=0.0.0.0
DB_PORT=3306
DB_DRIVER=pdo_mysql
DB_DSN=mysql:dbname=${DB_NAME};host=${DB_HOST};port=${DB_PORT}

必要なファイルとディレクトリ構成について

今回は設定ファイルやマイグレーションファイルは var/doctrine のディレクトリ化に配置するようにします。
DoctrineMigrationsではマイグレーション用の設定ファイルと、データベースコネクション用のファイルを用意します。
今回はphpファイルで用意しますが、yamlでも設定することは可能です。

まずはmigration.phpを用意する

var以下にディレクトリを用意します。

1
$ mkdir -p var/doctrine/migrations

次に var/doctrine に移動し、migrations.phpを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
// var/doctrine/migrations.php
return [
    'table_storage' => [
        'table_name' => 'doctrine_migration_versions',
        'version_column_name' => 'version',
        'version_column_length' => 191,
        'executed_at_column_name' => 'executed_at',
        'execution_time_column_name' => 'execution_time',
    ],

    'migrations_paths' => [
      'Polidog\\DoctrineMigrationExample\\Migrations' => __DIR__ . '/migrations'
    ],

    'all_or_nothing' => true,
    'transactional' => true,
    'check_database_platform' => true,
    'organize_migrations' => 'year_and_month',
    'connection' => null,
    'em' => null,
];

migrations-db.phpとmigrations-db-test.phpを用意する

データベース接続用のファイルを2つ用意します。
通常用に migrations-db.php , テスト用には migrations-db-test.php を使用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// var/doctrine/migrations-db.php

<?php

use BEAR\Dotenv\Dotenv;

require_once dirname(__DIR__, 2) . '/vendor/autoload.php';

(new Dotenv())->load(dirname(__DIR__, 2));

return [
    'dbname' => getenv('DB_NAME'),
    'user' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'host' => getenv('DB_HOST'),
    'port' => getenv('DB_PORT'),
    'driver' => getenv('DB_DRIVER')
];
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php
// var/doctrine/migrations-db-test.php

use BEAR\Dotenv\Dotenv;

require_once dirname(__DIR__, 2) . '/vendor/autoload.php';

(new Dotenv())->load(dirname(__DIR__, 2));

return [
    'dbname' => getenv('DB_NAME') . '_test',
    'user' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'host' => getenv('DB_HOST'),
    'port' => getenv('DB_PORT'),
    'driver' => getenv('DB_DRIVER')
];

マイグレーションファイルを生成する

ここまで設定が完了したらマイグレーションファイルを生成します。 デフォルトの設定ファイル、DB接続ファイルの位置とは違うので、configuration, db-configuration のオプションを指定する必要があります。

1
$ vendor/bin/doctrine-migrations migrations:generate --configuration=var/doctrine/migrations.php --db-configuration=var/doctrine/migration-db.php

実行することでvar/doctrine/migrations/{year}/{month}/VersionXXXXXX.php というファイルが生成されているかと思います。 今回の自分の環境だと ``var/doctrine/migrations/2024/03/Version20240312153132.php` が生成されました。

中身は以下のようになっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

declare(strict_types=1);

namespace Polidog\DoctrineMigrationExample\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * Auto-generated Migration: Please modify to your needs!
 */
final class Version20240312153132 extends AbstractMigration
{
    public function getDescription(): string
    {
        return '';
    }

    public function up(Schema $schema): void
    {
        // this up() migration is auto-generated, please modify it to your needs

    }

    public function down(Schema $schema): void
    {
        // this down() migration is auto-generated, please modify it to your needs

    }
}

試しにユーザーテーブルを作るコードを書いてみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php

declare(strict_types=1);

namespace Polidog\DoctrineMigrationExample\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * Auto-generated Migration: Please modify to your needs!
 */
final class Version20240312153132 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'Create user table';
    }

    public function up(Schema $schema): void
    {
        $table = $schema->createTable('users');
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
        $table->addColumn('username', 'string', ['length' => 255]);
        $table->addColumn('avatar_url', 'string', [
            'length' => 255,
            'notnull' => true,
            'default' => null
        ]);
        $table->addColumn("created_at", "datetime", [
            "notnull" => false,
            "default" => null
        ]);
        $table->addColumn("updated_at", "datetime", [
            "notnull" => false,
            "default" => null
        ]);

        $table->setPrimaryKey(['id']);
    }

    public function down(Schema $schema): void
    {
        $schema->dropTable("authors");
    }
}

ファイルが用意できたら次にmigrationを実行してみましょう。

1
$ vendor/bin/doctrine-migrations migrations:migrate --configuration=var/doctrine/migrations.php --db-configuration=var/doctrine/migration-db.php

これでテーブルが作成されていると思います。

composer scriptsにmigrate, generateコマンドを定義する

マイグレーションファイルの生成、適用は毎回手で入力するとめんどくさいのでcomposer scriptsに定義すると便利です。

1
2
3
...
        "migrations:generate": "vendor/bin/doctrine-migrations migrations:generate --configuration=var/doctrine/migrations.php --db-configuration=var/doctrine/migrations-db.php",
        "migrations:migrate": "vendor/bin/doctrine-migrations migrations:migrate --configuration=var/doctrine/migrations.php --db-configuration=var/doctrine/migrations-db.php"

定義できたら以下のようにコマンドが使えるようになります。

1
2
$ composer migrations:generate
$ composer migrations:migrate

bin/setup.phpを活用する

BEAR.Sundayではプロジェクト生成時に bin/setup.php が生成されます。
チケットチュートリアルでも使っていましたが、マイグレーションやデータベースの生成はsetupで定義すると便利です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
// bin/setup.php

declare(strict_types=1);

use BEAR\Dotenv\Dotenv;
require_once dirname(__DIR__) . '/vendor/autoload.php';
(new Dotenv())->load(dirname(__DIR__));

chdir(dirname(__DIR__));
passthru('rm -rf ./var/tmp/*');

// データベースの作成
$pdo = new \PDO(getenv('DB_DSN'), getenv('DB_USER'), getenv('DB_PASSWORD'));
$pdo->exec('CREATE DATABASE IF NOT EXISTS ' . getenv('DB_NAME'));
$pdo->exec('DROP DATABASE IF EXISTS ' . getenv('DB_NAME') . '_test');
$pdo->exec('CREATE DATABASE ' . getenv('DB_NAME') . '_test');

// migrationの実行
$migrationsConfigPath = dirname(__DIR__) . '/var/doctrine/migrations.php';
$dbConfigPath = dirname(__DIR__) . '/var/doctrine/migrations-db.php';
$dbConfigTestPath = dirname(__DIR__) . '/var/doctrine/migrations-db-test.php';
passthru("vendor/bin/doctrine-migrations migrations:migrate --configuration=$migrationsConfigPath --db-configuration=$dbConfigPath --no-interaction ");
passthru("vendor/bin/doctrine-migrations migrations:migrate --configuration=$migrationsConfigPath --db-configuration=$dbConfigTestPath --no-interaction ");

このように定義できたら以下のコマンドを実行します。

1
$ php bin/setup.php 

もしくは以下のコマンドでも大丈夫です。

1
$ composer setup

今回のサンプルコードについて

Github上でコードを公開しています。
polidog/Polidog.DoctrineMigrationExample

最後に

今回はBEAR.SundayでDoctrine Migrationsを使う方法をご紹介しました。
この個人ブログをBEAR.Sundayで作り直そうと思っているので、今後も何かしらのBEAR.Sundayを使った知見を共有できればと考えています。

この記事を読んだ皆さんもぜひBEAR.Sundayを触ってみてください。きっと好きになります。

参考記事

comments powered by Disqus
Built with Hugo
テーマ StackJimmy によって設計されています。