Symfony Doctrine Migrations upgrade to version 3

Introduction

Before we begin, you should take a look at one of my previous articles “How to solve Symfony 5 and Doctrine Migrations Bundle 3 upgrade error: Unrecognized options “dir_name, namespace” under “doctrine_migrations”.” That article covers the base case when you don’t have any migrations and, technically, everything worked fine — until actual migrations needed to be migrated to the new Doctrine Bundle version.

This article covers what needs to be done in order to update existing migrations.

Update for existing migrations

If you have followed the first article, you will encounter further post-update issues if you have migrations that were already executed before the Doctrine bundle upgrade. To resolve the issues, follow these steps:

Make sure to have the correct environment loaded

This was covered in the original article, but let’s make sure it’s done before proceeding. If you had any other environment set in the .env file, the upgrade could rewrite it and set the environment back to dev. Make sure to revert it back to the proper environment (In my case, it was local).

Move the existing migration files

Move (cut and paste) your existing migrations (their .php files) to the new Doctrine migrations folder.

Previous Doctrine migrations folder was src/Migrations while the new one is migrations (relative to your project root directory). To make sure you’re using the correct folder, open config/packages/doctrine_migrations.yaml file and look for migration_paths configuration option. It should contain the following (new) namespace definition and its directory 'DoctrineMigrations': '%kernel.project_dir%/migrations'.

Sync Doctrine metadata storage

Run php bin/console doctrine:migrations:sync-metadata-storage.

Doctrine changed its migrations version database table in version 3.0. The default table name in 2.x was migration_versions and the new table name is doctrine_migration_versions. The table structure is different in 3.0 as well — a new column execution_time is introduced which contains an amount of milliseconds the migration took when it was executed. The sync-metadata-storage command should create the new doctrine_migration_versions database table for you.

Import data from the old migration versions table

The previous command set up the new default Doctrine migrations database table. The only thing left to do now is to let Doctrine know that you’ve already executed some migrations in the previous version.

To do that, run the following MySQL query:

INSERT INTO doctrine_migration_versions (version, executed_at, execution_time) SELECT concat("DoctrineMigrations\\Version", version), executed_at, 1 FROM migration_versions;

This query does a couple of things:

  • version column in the old table contained only migration timestamp (ex. 20200820072236). The new Doctrine bundle supports multiple namespaces, the default one being DoctrineMigrations. So, in order to transfer the old migrations to the new table, we’re adding DoctrineMigrations\Version as a prefix in order to get the new format: DoctrineMigrations\Version2020082007226

  • We are adding a sample value 1 as the value of new execution_time column. You can put anything here, since it only marks the amount of milliseconds a migration took when executed.

Cleanup the old table

If everything up until now went smoothly, the old migration_versions table is now obsolete. But, before deleting it, verify that the migrations are upgraded successfully with php bin/console doctrine:migrations:status. If Executed Unavailable value is 0 we should be fine.

Just as a precaution, export the structure and data of the old migration_versions table. After a breaking, backwards incompatible change like this, you never know if anything else is going to break in the future.

You can now delete migration_versions table from the database.

Conclusion

We have done the following:

  • Moved the old migration php files to the new migrations directory;

  • Synced Doctrine migrations metadata storage;

  • Let Doctrine create the new default doctrine_migration_versions;

  • Convert to the new format and import the old migrations to the new database table;

  • Verify that the upgrade went smoothly;

  • Backup (export) the old migration_versions database table and then delete it.

That’s it for now. This should conclude the Doctrine migrations bundle upgrade to version 3.0.