この記事では、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
でマイグレーションを生成し、スクラッチからマイグレーションを実装することもできますが、ここではエンティティクラスの作成・変更した後に、現在のデータベースとの差分からマイグレーションを自動生成する手順を説明します。
この場合、開発の流れは以下のようになります。
- エンティティクラスを作成または変更
doctrine:migrations:diff
でマイグレーションを自動生成- 必要に応じてマイグレーションを修正
- マイグレーションを適用
エンティティクラスの作成・変更
タイトルとコンテンツのみをフィールドに持つブログ投稿のエンティティをサンプルとして作成してみます。
$ 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)