doctrine/DoctrineMigrationsBundle

Command "bin/console doctrine:schema:update --complete" also intends to drop the version table.

AndreasA opened this issue ยท 8 comments

I just noticed that if I run

bin/console doctrine:schema:update --dump-sql --complete it outputs:
DROP TABLE doctrine_migration_versions;

If i run it, it does indeed drop the table. It is not that important as I use migrations to change the schema anyway, but it should still be excluded.

Using
doctrine/dbal: 3.4.4
doctrine/orm: 2.13.1
doctrine/doctrine-bundle: 2.7.0
doctrine/doctrine-migrations-bundle: 3.2.2

Of course, excluding the table to the schema_filter has other issues like executed migrations not being detected.

I can approve this behavior.

โฏ symfony console doctrine:schema:update --force --no-interaction --complete --dump-sql
DROP TABLE doctrine_migration_versions;

 Updating database schema...

     1 query was executed

                                                                                                                        
 [OK] Database schema updated successfully!                                                                             
                                                                                                                        
gjuric commented

It seems like this is related to the --complete option being used. There is an issue regarding that created in the doctrine/migrations package: doctrine/migrations#1317

May it be worth going in the same way (symfony/symfony#36655) as Symfony does for its Doctrine transport for Messenger and automatically add doctrine_migration_versions into schema?

Unfortunately, it looks like filtering of the doctrine_migration_versions breaks the migration process itself because the same schema filter is applied for the migration process itself.

I end up with this solution for Symfony 6 application:

<?php

declare(strict_types=1);

namespace App\Doctrine\Dbal\SchemaAssetFilter;

use Doctrine\DBAL\Schema\AbstractAsset;
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\Tools\Console\Command\DoctrineCommand;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Prevent Doctrine migrations tracking table to be dropped by the Doctrine's schema tool
 */
#[AutoconfigureTag('doctrine.dbal.schema_filter')]
class DoctrineMigrationsFilter implements EventSubscriberInterface
{
    private bool $enabled = true;

    public function __invoke(AbstractAsset|string $asset): bool
    {
        if (!$this->enabled) {
            return true;
        }
        if (!class_exists(TableMetadataStorageConfiguration::class)) {
            return true;
        }
        if ($asset instanceof AbstractAsset) {
            $asset = $asset->getName();
        }
        return $asset !== (new TableMetadataStorageConfiguration())->getTableName();
    }

    public function onConsoleCommand(ConsoleCommandEvent $event): void
    {
        $command = $event->getCommand();
        if ($command === null) {
            return;
        }
        /**
         * Any console commands from the Doctrine Migrations bundle may attempt
         * to initialize migrations information storage table. Because of this
         * they should not be affected by this filter because their logic may
         * get broken since they will not "see" the table, they may try to use
         */
        if ($command instanceof DoctrineCommand) {
            $this->enabled = false;
        }
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ConsoleEvents::COMMAND => 'onConsoleCommand',
        ];
    }
}

However, it is certainly a workaround and a bit hacky because it depends on the pre-collected list of console command classes where the filter should be disabled. But it works, hope it will be helpful for somebody else too.

However, it is certainly a workaround and a bit hacky because it depends on the pre-collected list of console command classes where the filter should be disabled.

@FlyingDR According to your edit, this is no longer true I think ๐Ÿ™‚

@FlyingDR According to your edit, this is no longer true I think ๐Ÿ™‚

@greg0ire Indeed :)