aygon/doctrine-migrations-bundle
Install the Bundle
composer require aygon/doctrine-migrations-bundle
Add to config/bundles.php:
return [
// ...
Aygon\DoctrineMigrationsBundle\AygonDoctrineMigrationsBundle::class => ['all' => true],
];
Configure the Bundle
Update config/packages/doctrine_migrations.yaml (create if missing):
doctrine_migrations:
dir_name: '%kernel.project_dir%/src/Migrations'
namespace: 'App\Migrations'
table_name: 'migration_versions'
name: 'DoctrineMigrations'
Generate Your First Migration
php bin/console doctrine:migrations:generate --name="Initial migration"
This creates a migration file in src/Migrations/VersionYYYYMMDDHHMMSS.php.
Execute the Migration
php bin/console doctrine:migrations:migrate
Use this bundle to version-control database schema changes (e.g., adding a column, modifying a table). For example:
# After altering a schema in your entities:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:generate --name="Add user_email_index"
php bin/console doctrine:migrations:migrate
Schema Changes → Migration → Deployment
email to User).php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:generate --name="Add email to User"
php bin/console doctrine:migrations:migrate
Rollbacks
Use --down to revert:
php bin/console doctrine:migrations:migrate --down
Or target a specific version:
php bin/console doctrine:migrations:migrate 20230101000000
Testing Migrations
In phpunit.xml, add:
<env name="KERNEL_CLASS" value="App\Kernel"/>
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak"/>
Run migrations in tests with:
php bin/console doctrine:migrations:migrate --env=test
Custom Migration Classes
Extend Doctrine\Migrations\AbstractMigration for non-schema changes (e.g., data seeding):
namespace App\Migrations;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
class Version20230101000001 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('INSERT INTO users (id, email) VALUES (1, "test@example.com")');
}
}
Environment-Specific Migrations
Use --env=prod or --env=dev to target specific configurations.
Dry Runs Preview SQL without executing:
php bin/console doctrine:migrations:migrate --dry-run
Namespace/Path Mismatches
dir_name and namespace in doctrine_migrations.yaml match your migration files.Class 'App\Migrations\Version...' not found → Verify the namespace and file location.Database Connection Issues
doctrine_migrations:
connection: 'secondary_db'
Locking Conflicts
migration_versions table. Avoid running multiple migration processes simultaneously.--allow-no-migration to bypass checks (not recommended for production).Schema Changes Without Migrations
Time-Based Naming Collisions
--name explicitly to avoid VersionYYYYMMDDHHMMSS clashes.php bin/console doctrine:migrations:status
config/packages/dev/doctrine.yaml:
dbal:
logging: true
profiling: true
php bin/console doctrine:migrations:version --delete --all
php bin/console doctrine:migrations:migrate
Custom Migration Commands Extend the bundle by creating a custom command:
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
use Doctrine\Migrations\Configuration\Migration\PhpFile;
class CustomMigrationCommand extends Command
{
protected function configure(): void
{
$this->setName('app:migrate:custom');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$config = new PhpFile('src/Migrations');
$connection = new ExistingConnection(/* your connection */);
$migration = new \Doctrine\Migrations\Tools\Console\Command\MigrateCommand();
return $migration->run($input, $output, $config, $connection);
}
}
Post-Migration Hooks
Use the postMigrate event in a listener:
namespace App\EventListener;
use Doctrine\Migrations\Event\PostMigrationEventArgs;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MigrationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'migrations.post_migrate' => 'onPostMigrate',
];
}
public function onPostMigrate(PostMigrationEventArgs $args): void
{
// Send notification, log, or trigger other actions
}
}
Multi-Database Support For multi-DB setups, configure separate migration tables per connection:
doctrine_migrations:
connections:
default:
table_name: 'migration_versions'
secondary:
table_name: 'migration_versions_secondary'
How can I help you explore Laravel packages today?