Symfony 3 DoctrineMigrationsBundleの使い方


この記事では、DoctrineMigrationsBundleのセットアップ手順と、マイグレーションの作成・適用手順についてまとめてみました。

Symfonyは、デフォルトではマイグレーション機構が含まれていません。
また、doctrine:schema:update --forceコマンドを使ってデータベースにスキーマを反映することができますが、デフォルトではProduction環境で利用できないためマイグレーションを導入したほうが無難です。

Symfonyでマイグレーションを実装するには、DoctrineMigrationsBundle (Github: doctrine/DoctrineMigrationsBundle)を導入します。

インストールと設定

composerでパッケージを追加

$ composer require doctrine/doctrine-migrations-bundle "^1.0"

Bundleの読み込みを追加

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        //...
        new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
    );
}

app/config/config.ymlに以下の設定を追加

# app/config/config.yml
doctrine_migrations:
    dir_name: "%kernel.root_dir%/DoctrineMigrations"
    namespace: Application\Migrations
    table_name: migration_versions
    name: Application Migrations
設定プロパティ 説明
dir_name マイグレーションファイルを配置するディレクトリ
namespace マイグレーションの名前空間
table_name 適用されたマイグレーションのバージョンを記録するテーブルの名前
name マイグレーションの名前

以上で、開発環境でマイグレーションを実装することができるようになります。

マイグレーションの作成

マイグレーションは、doctrine:migrations:generateでマイグレーションを生成し、スクラッチからマイグレーションを実装することもできますが、ここではエンティティクラスの作成・変更した後に、現在のデータベースとの差分からマイグレーションを自動生成する手順を説明します。

この場合、開発の流れは以下のようになります。

  1. エンティティクラスを作成または変更
  2. doctrine:migrations:diffでマイグレーションを自動生成
  3. 必要に応じてマイグレーションを修正
  4. マイグレーションを適用

エンティティクラスの作成・変更

タイトルとコンテンツのみをフィールドに持つブログ投稿のエンティティをサンプルとして作成してみます。

$ bin/console doctrine:generate:entity

...

The Entity shortcut name: AppBundle:Post

...

New field name (press <return> to stop adding fields): title
Field type [string]:
Field length [255]:
Is nullable [false]:
Unique [false]:

New field name (press <return> to stop adding fields): content
Field type [string]: text
Is nullable [false]: true
Unique [false]:

New field name (press <return> to stop adding fields):


  Entity generation


  created ./src/AppBundle/Entity/
  created ./src/AppBundle/Entity/Post.php
> Generating entity class src/AppBundle/Entity/Post.php: OK!
> Generating repository class src/AppBundle/Repository/PostRepository.php: OK!


  Everything is OK! Now get to work :).

マイグレーションの作成

ブログ投稿エンティティを作成した後、doctrine:migrations:diffを実行するとブログ投稿を保存するテーブルを作成するマイグレーションを自動で生成してくれます。

$ bin/console doctrine:migrations:diff
Generated new migration class to "/Users/hrendoh/workspace/symfony-migration/app/DoctrineMigrations/Version20171127040254.php" from schema differences.
<?php

namespace Application\Migrations;

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

/**
 * Auto-generated Migration: Please modify to your needs!
 */
class Version20171127040254 extends AbstractMigration
{
    /**
     * @param Schema $schema
     */
    public function up(Schema $schema)
    {
        // this up() migration is auto-generated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('CREATE TABLE post (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, content LONGTEXT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
    }

    /**
     * @param Schema $schema
     */
    public function down(Schema $schema)
    {
        // this down() migration is auto-generated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('DROP TABLE post');
    }
}

設定dir_nameに指定されたディレクトリが作成され、そこにマイグレーションファイルが生成されてます。

また、データベースを確認するとpostテーブルと適用されたマイグレーションを記録するmigration_versionsテーブルが作られています。

mysql> show tables;
+-----------------------------+
| Tables_in_symfony-migration |
+-----------------------------+
| migration_versions          |
| post                        |
+-----------------------------+
2 rows in set (0.00 sec)

補足:

migration_versionsテーブルは、doctrine:migrations:status初回実行時にも自動で作成されます。

自動生成されたマイグレーションの修正

自動生成されたマイグレーションに不足がある場合、直接修正します。

ただし、DoctrineMigrationsBundleは、インデックスや、参照カラムの外部キー制約などもきっちり定義してくれるので、基本的には修正することはあまり無さそうです。

マイグレーションの適用

doctrine:migrations:migrateコマンドで、マイグレーションを適用します。

$ bin/console doctrine:migrations:migrate

                    Application Migrations


WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y
Migrating up to 20171127040254 from 0

  ++ migrating 20171127040254

     -> CREATE TABLE post (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, content LONGTEXT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB

  ++ migrated (0.12s)

  ------------------------

  ++ finished in 0.12s
  ++ 1 migrations executed
  ++ 1 sql queries

doctrine:migrations:statusコマンドで現在のステータスを確認できます。

$ bin/console doctrine:migrations:status

 == Configuration

    >> Name:                                               Application Migrations
    >> Database Driver:                                    pdo_mysql
    >> Database Name:                                      symfony-migration
    >> Configuration Source:                               manually configured
    >> Version Table Name:                                 migration_versions
    >> Version Column Name:                                version
    >> Migrations Namespace:                               Application\Migrations
    >> Migrations Directory:                               /Users/hrendoh/workspace/symfony-migration/app/DoctrineMigrations
    >> Previous Version:                                   0
    >> Current Version:                                    2017-11-27 04:02:54 (20171127040254)
    >> Next Version:                                       Already at latest version
    >> Latest Version:                                     2017-11-27 04:02:54 (20171127040254)
    >> Executed Migrations:                                1
    >> Executed Unavailable Migrations:                    0
    >> Available Migrations:                               1
    >> New Migrations:                                     0

マイグレーションのバージョンをdownする場合は、以下のようにdoctrine:migrations:executeコマンドに、現在のバージョンをYYYYMMDDHHmmss形式で指定し、--downオプションを付けて実行します。

$ bin/console doctrine:migrations:execute YYYYMMDDHHMMSS --down
WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y

  -- reverting 20171127040254

     -> DROP TABLE post

  -- reverted (0.09s)
,