Skip to content

Instantly share code, notes, and snippets.

@bendavies
Last active September 2, 2025 11:06
Show Gist options
  • Select an option

  • Save bendavies/b2eff14b71fbdf1afa3921a94928efde to your computer and use it in GitHub Desktop.

Select an option

Save bendavies/b2eff14b71fbdf1afa3921a94928efde to your computer and use it in GitHub Desktop.
DBAL V4 Migration

Doctrine DBAL v4 Migration - Ignore Custom Indexes

This gist contains the files needed to ignore custom PostgreSQL indexes (trigram, tsvector, etc.) when migrating from Doctrine DBAL v3 to v4.

File 1: src/Doctrine/DBAL/Middleware/PostgreSQLPlatformMiddleware.php

<?php

declare(strict_types=1);

namespace App\Doctrine\DBAL\Middleware;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsMiddleware;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

#[AsMiddleware(connections: ['default'])]
final class PostgreSQLPlatformMiddleware implements Middleware
{
    #[\Override]
    public function wrap(Driver $driver): Driver
    {
        return new PostgreSQLPlatformDriver($driver);
    }
}

File 2: src/Doctrine/DBAL/Middleware/PostgreSQLPlatformDriver.php

<?php

declare(strict_types=1);

namespace App\Doctrine\DBAL\Middleware;

use App\Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use App\Doctrine\DBAL\Schema\PostgreSQLSchemaManager;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use Doctrine\DBAL\Platforms\AbstractPlatform;

final class PostgreSQLPlatformDriver extends AbstractDriverMiddleware
{
    #[\Override]
    public function createDatabasePlatformForVersion($version): AbstractPlatform
    {
        return new PostgreSQLPlatform();
    }

    #[\Override]
    public function getDatabasePlatform(): AbstractPlatform
    {
        return new PostgreSQLPlatform();
    }

    /**
     * For compatibility with older doctrine/dbal 3. can be removed once on doctrine/dbal 4
     * https://github.com/doctrine/dbal/pull/5458
     */
    #[\Override]
    public function getSchemaManager(Connection $conn, AbstractPlatform $platform)
    {
        return new PostgreSQLSchemaManager($conn, $platform);
    }
}

File 3: src/Doctrine/DBAL/Platforms/PostgreSQLPlatform.php

<?php

declare(strict_types=1);

namespace App\Doctrine\DBAL\Platforms;

use App\Doctrine\DBAL\Schema\PostgreSQLSchemaManager;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform as BasePostgreSQLPlatform;
use Doctrine\DBAL\Schema\PostgreSQLSchemaManager as BasePostgreSQLSchemaManager;
use Doctrine\DBAL\Schema\SchemaManagerFactory;

final class PostgreSQLPlatform extends BasePostgreSQLPlatform implements SchemaManagerFactory
{
    #[\Override]
    public function createSchemaManager(Connection $connection): BasePostgreSQLSchemaManager
    {
        return new PostgreSQLSchemaManager($connection, $this);
    }
}

File 4: src/Doctrine/DBAL/Schema/PostgreSQLSchemaManager.php

<?php

declare(strict_types=1);

namespace App\Doctrine\DBAL\Schema;

use Doctrine\DBAL\Schema\PostgreSQLSchemaManager as BasePostgreSQLSchemaManager;

final class PostgreSQLSchemaManager extends BasePostgreSQLSchemaManager
{
    private const IGNORE_INDEXES = [
        'users' => [
            'users_email_trgm',
            'users_name_trgm',
        ],
    ];

    #[\Override]
    protected function _getPortableTableIndexesList($tableIndexes, $tableName = null): array
    {
        $indexes = parent::_getPortableTableIndexesList($tableIndexes, $tableName);
        if ($tableName !== null && isset(self::IGNORE_INDEXES[$tableName])) {
            $indexes = array_filter($indexes, function ($index) use ($tableName) {
                return !in_array($index->getName(), self::IGNORE_INDEXES[$tableName], true);
            });
        }
        return $indexes;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment