Migrar de Doctrine 2 a Doctrine 3

Migrar de Doctrine 2 a Doctrine 3

Fa uns mesos a l'empresa a la que treballo vam estar migrant alguns dels paquets que utilitzem, per tal d'actualitzar les versions de PHP i altres sistemes. Abans d'arribar a aquell punt, habiem d'actualitzar Doctrine de la versió 2.* a la 3.*.

Quin va ser el problema? Que en actualitzar la versió de Doctrine, aquesta nova versió, esperaba una nova taula anomenada "doctrine_migrations_versions" en comptes de la classica "migrations_versions". Podría no ser cap drama, si no fos per que aquesta nova taula inesperada provoca que s'executin TOTES les migracions que existents a la aplicació actual. Es a dir executa tots els UP de les migracions. I dependrà de com de bé i/o malament estiguin aquestes migracions per que el desastre estigui assegurat.

Si en aquestes migracions hi ha drops, inserts o altres coses que no fan un check previ si la taula existeix, o si alguna columna existeix o no, el desastre pot ser monumental. Per això abans de fer aquest update, us aconsello aquesta migració:

<?php

declare(strict_types=1);

namespace src\Infrastructure\Persistence\Doctrine\Migrations;

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

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

    public function up(Schema $schema) : void
    {
        $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('
            CREATE TABLE doctrine_migration_versions (
              version varchar(191) COLLATE utf8_unicode_ci NOT NULL,
              executed_at datetime DEFAULT NULL,
              execution_time int(11) DEFAULT NULL,
              PRIMARY KEY (version)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
        ');

        $this->addSql('
            INSERT INTO doctrine_migration_versions (
                version, 
                executed_at, 
                execution_time
            ) 
            SELECT concat("src\\\Infrastructure\\\Persistence\\\Doctrine\\\Migrations\\\Version", version), 
                   executed_at, 
                   1 
            FROM migration_versions
        ');

        $this->addSql('
            INSERT INTO doctrine_migration_versions (
                version, 
                executed_at, 
                execution_time
            ) 
            VALUES (
               "src\\\Infrastructure\\\Persistence\\\Doctrine\\\Migrations\\\Version20220826082028", 
               NOW(), 
               1
               ) 
        ');
    }

    public function down(Schema $schema) : void
    {
        $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('DROP TABLE IF EXISTS doctrine_migration_versions');
    }

    public function isTransactional(): bool
    {
        return false;
    }
}

Si ho copieu, assegureu-vos de canviar el namespace src\Infrastructure\Persistence\Doctrine\Migrations pel vostre i el nom de la versió Version20220826082028 pel nom que hagi de tenir per seguir l'ordre de les vostres migracions.

Haureu de còrrer aquesta migracio ABANS de fer el update de Doctrine, ja que si intenteu instalar la nova versió abans, aquesta us alterarà el que abans hem comentat.

Si teniu alguna altre alternativa a la que us proposo, compartiu-la!