Как добавить новую колонку и уникальный индекс для нее в непустую таблицу

Пример кода, который добавляет новую колонку и уникальный индекс для нее:

<?php

namespace Acme\Bundle\ShippingBundle\Migrations\Schema\v1_0;

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Types;
use Oro\Bundle\EntityBundle\EntityConfig\DatagridScope;
use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope;
use Oro\Bundle\EntityExtendBundle\Migration\OroOptions;
use Oro\Bundle\MigrationBundle\Migration\Extension\DatabasePlatformAwareInterface;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\ParametrizedSqlMigrationQuery;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;

/**
 * Class AddExternalIdToShippingMethodsConfigsRule.
 *
 * @package Acme\Bundle\ShippingBundle\Migrations\Schema\v1_0
 */
class AddExternalIdToShippingMethodsConfigsRule implements Migration, DatabasePlatformAwareInterface
{

    /**
     * @var AbstractPlatform
     */
    protected $platform;

    /**
     * {@inheritdoc}
     */
    public function setDatabasePlatform(AbstractPlatform $platform): void
    {
        $this->platform = $platform;
    }

    /**
     * @param Schema $schema
     * @param QueryBag $queries
     *
     * @throws DBALException
     * @throws SchemaException
     */
    public function up(Schema $schema, QueryBag $queries): void
    {
        if (!$table = $schema->getTable('oro_ship_method_configs_rule')) {
            return;
        }

        $this->addExternalId($schema, $queries, $table);
    }

    /**
     * @param Schema $schema
     * @param QueryBag $queries
     * @param Table $table
     *
     * @throws SchemaException
     */
    protected function addExternalId(Schema $schema, QueryBag $queries, Table $table): void
    {
        // Add a new column "external_id" as nulalble first to prevent error during migration.
        $table->addColumn('external_id', Types::STRING, ['notnull' => false, OroOptions::KEY => [
            'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
            'datagrid' => ['is_visible' => DatagridScope::IS_VISIBLE_TRUE, 'order' => 0, 'show_filter' => true],
            'form' => ['is_enabled' => true],
            'view' => ['is_displayable' => true],
            'dataaudit' => ['auditable' => true],
        ]]);

        // Fill new created column "external id" with existing "id" to have possibility make it not nullable.
        $queries->addQuery(
            new ParametrizedSqlMigrationQuery('UPDATE oro_ship_method_configs_rule SET external_id = id')
        );
 
        $postSchema = clone $schema;
        $postSchema
            ->getTable($table->getName())
            // Update new created column "external_id" and make it not nullable.
            ->changeColumn('external_id', ['notnull' => true])
            // Add a unique index for new created column "external_id".
            ->addUniqueIndex(['external_id'], 'uidx_oro_ship_method_configs_rule_external_id');

        foreach ($this->getSchemaDiff($schema, $postSchema) as $query) {
            $queries->addPostQuery($query);
        }
    }

    /**
     * @param Schema $schema
     * @param Schema $toSchema
     *
     * @return string[]
     */
    protected function getSchemaDiff(Schema $schema, Schema $toSchema): array
    {
        return (new Comparator())->compare($schema, $toSchema)->toSql($this->platform);
    }
}
Benya