LoginSignup
3
2

More than 3 years have passed since last update.

DoctrineMigrationsBundle 2 → 3 メジャーバージョンアップ対応

Posted at

概要

SymfonyアプリでDBマイグレーションをやってくれる DoctrineMigrationsBundle の3系が2020年06月にリリースされました。

2系から3系へのメジャーバージョンアップ対応を記します :pencil:

環境

  • PHP 7.2
  • Symfony 4.4
  • DoctrineMigrationsBundle 2.1.2 --> 3.0.1
  • MySQL 5.6

本題

変更点等は UPGRADE.md に記されています

doctrine/doctrine-migrations-bundle パッケージは
doctrine/migrations パッケージを require しているので、こちらの UPGRADE.md も読んでおくといいかもです

要点としては以下です

  • 『マイグレーションテーブルの更新』
    • テーブル名: これまで migration_versions がデフォルトでしたが、 doctrine_migration_versions がデフォルトになります(設定で変更可能)
    • カラム
      • version : これまで 20200601000000 のように YmdHis フォーマットでしたが、3系からは FQCN (Fully Qualified Class Name)になります
      • execution_time : 新規に追加されます。マイグレーションにかかった時間を格納するようです。既存の executed_at (マイグレーションを適用した日時)とは別カラムになります
  • Code BC Breaks
    • いくつかのクラスが final classになっていたり、削除されていたりします

『Code Bc Breaks』 については、各自のアプリケーションでの実装次第となりそうなので、
final classになったものについては継承する形式をやめて construct で内包する形に変更するなどの対応になるかと思います。

この記事では、
共通してつまづきそうな『マイグレーションテーブルの更新』について記します。

『マイグレーションテーブルの更新』に合わせて、 doctrine_migrtions の設定方法が変わりました :rotating_light:

変更点は主に以下の2つです
- マイグレーションファイルのディレクトリ・namespaceの設定方法の変更
- マイグレーションテーブルの設定方法の変更

マイグレーションファイルのディレクトリ・namespaceの設定方法の変更

マイグレーションファイルを保存してあるディレクトリに合わせて以下の設定を加えます

After は、デフォルトの値になるので、各自アプリケーションでのディレクトリ・namespaceに合わせて設定する必要があります

デフォルトと異なる場合、合わせて指定してあげないと「マイグレーションファイルが存在しない」と認識されエラーになります

Before ※ 元々、設定がない場合もあります

doctrine_migrations:
    dir_name: '%kernel.project_dir%/src/Migrations'
    namespace: DoctrineMigrations

After

doctrine_migrations:
    migrations_paths:
        DoctrineMigrations: '%kernel.project_dir%/src/Migrations'
        # 👆 ここが {namespace}: {dir_name} となるように設定します

例えば、以下のようなファイル構成と namespace であれば、デフォルトのままで問題ないですが、
どちらかでもカスタムしていれば合わせて設定してください

% tree ./path_to_app/src
..
├── Migrations  # 👈 {dir_name} として設定
│   ├── Version20200601000000.php 
│   ├── Version20200602000000.php 
..
namespace DoctrineMigrations; # 👈 {namespace} として設定

final class Version20200601000000 extends AbstractMigration
{
  .. 

マイグレーションテーブルの設定方法の変更

次にマイグレーションテーブルの設定方法も変更になりました。

デフォルトのテーブル名が migration_versions から doctrine_migration_versions に変わったので、
既存のマイグレーションテーブルをそのまま使うのであれば、指定してあげる必要があります。

Before ※ 元々、設定がない場合もあります

doctrine_migrations:
    table_name: 'migration_versions'
    column_name: 'version'
    column_length: 14
    executed_at_column_name: 'executed_at'

After

doctrine_migrations:
    storage:
        table_storage:
            table_name: 'migration_versions'       # 注意①
            version_column_name: 'version'         # 元々、versionsカラムであれば指定しなくても大丈夫です
            version_column_length: 191             # 注意②
            executed_at_column_name: 'executed_at' # 元々、executed_atカラムであれば指定しなくても大丈夫です

注意① table_name

3系からデフォルトのマイグレーションテーブルのテーブル名は doctrine_migration_versions に変更されます。

おそらく(?)みなさんのマイグレーションテーブルのテーブル名は指定して作成していなければ migration_versions のはずなので、
3系からは設定で指定してあげる必要があります。

そうとは知らず、省略していると、 doctrine_migration_versions テーブルが新規作成され、1からマイグレーションが実行されてしまうので注意してください :rotating_light:

注意② version_column_length

3系から version カラムに入る値は 20200601000000 のように YmdHis フォーマットではなく FQCN になります。

2系のカラム長のデフォルト値 14 のままでは、 FQCN が入り切らない可能性があるため、3系では増えました。

UPGRADE.md に記載のあるように 1024 を設定しまうと、 MySQL 5.6 ではエラーになってしまうので注意してください :rotating_light:

理由は、MySQL 5.6の単一カラムのインデックスキーは 767byte までしか指定できないからです。

なので 191 (191文字 * 4byte = 764byte < 767byte) ※ 4byte文字を考慮


execution_time カラムが追加されたこともあり、マイグレーションテーブルの2系と3系でどう変わるのか?は実際のデータを見てもらうのが早いので、以下に示します

2系

mysql> select * from migration_versions;
+----------------+---------------------+
| version        | executed_at         |
+----------------+---------------------+
| 20200601000000 | 2020-06-01 00:01:00 |
| 20200602000000 | 2020-06-02 00:01:00 |
..

3系

mysql> select * from migration_versions;
+------------------------------------------+---------------------+----------------+
| version                                  | executed_at         | execution_time |
+------------------------------------------+---------------------+----------------+
| DoctrineMigrations\Version20200601000000 | 2020-06-01 00:01:00 |             11 |
| DoctrineMigrations\Version20200602000000 | 2020-06-02 00:01:00 |             12 |
..

doctrine:migrations:migrate または doctrine:migrations:execute 実行時に、
3系のマイグレーションテーブルへ更新されます

execution_time カラムが追加されるだけではなく、
適用済みのマイグレーションの version の値についても、 FQCN への更新がされます!

1からマイグレーションが再実行されるわけではないのでご安心を。

以上で、『マイグレーションテーブルの更新』まわりでのメジャーバージョンアップ対応は完了になります。

ほとんどのケースで、これで対応完了になるのではないかと思っております :thought_balloon:


マイグレーションファイルでサービスコンテナを利用している場合

ここからは、少しレアケースで、なんらかの理由でマイグレーションファイルでサービスコンテナを利用している場合、
追加で対応してあげる必要があります

これまでは、以下のように ContainerAwareInterface を implements して use ContainerAwareTrait を宣言すれば、
自動でサービスコンテナがセットされていました。

が、3系からは自動でセットされません :confused:

class Version20200601000000 extends AbstractMigration implements ContainerAwareInterface
{
    use ContainerAwareTrait;

対応方法はこちらMigration Dependencies に記載されています

マイグレーション実行時にマイグレーションインスタンスの生成を
MigrationFactory 経由で生成しているところを、これを装飾した MigrationFactoryDecorator 経由に変更する(エイリアスをはる)ことで、
デコレータの装飾部分で ContainerAwareInterface のインスタンスであれば、サービスコンテナをセットするといった感じです。

        doctrine_migrations:
            services:
                 'Doctrine\Migrations\Version\MigrationFactory': 'App\Migrations\Factory\MigrationFactoryDecorator'
                 # 👆 MigrationFactory として MigrationFactoryDecorator を使用するように変更
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2