Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Migrations Bundle Laravel Package

doctrine/doctrine-migrations-bundle

Integrates Doctrine Migrations into Symfony apps, providing commands and configuration for versioned database schema changes. Generate, run, and rollback migrations across environments with reliable tracking and deployment-friendly workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require doctrine/doctrine-migrations-bundle
    

    Ensure doctrine/doctrine-bundle is also installed (required dependency).

  2. Configuration: Add the bundle to config/bundles.php:

    return [
        // ...
        Doctrine\Migrations\Bundle\DoctrineMigrationsBundle::class => ['all' => true],
    ];
    
  3. Generate Initial Migration:

    php bin/console doctrine:migrations:version --empty
    

    This creates a migrations/Versions directory and a VersionYYYYMMDDHHMMSS.php file.

  4. Create a New Migration:

    php bin/console make:migration
    

    This generates a new migration file with a timestamp in migrations/.

  5. Run Migrations:

    php bin/console doctrine:migrations:migrate
    

First Use Case

  • Schema Changes: Use migrations to alter database schema (e.g., adding columns, tables, or indexes). Example migration (up() method):
    public function up(SchemaManager $sm, Migration $migration): void
    {
        $this->addSql('ALTER TABLE users ADD COLUMN last_login DATETIME');
    }
    

Implementation Patterns

Workflows

  1. Local Development:

    • Run migrations locally with --dry-run to preview changes:
      php bin/console doctrine:migrations:migrate --dry-run
      
    • Rollback migrations if needed:
      php bin/console doctrine:migrations:migrate PREVIOUS_VERSION
      
  2. CI/CD Integration:

    • Use migrations in deployment pipelines to ensure database consistency.
    • Example GitHub Actions step:
      - name: Run Migrations
        run: php bin/console doctrine:migrations:migrate --allow-no-migration
      
  3. Multi-Environment Handling:

    • Use --env=prod to target specific environments:
      php bin/console doctrine:migrations:migrate --env=prod
      

Integration Tips

  1. Doctrine Events: Integrate migrations with Doctrine lifecycle events (e.g., postGenerateSchema):

    // config/packages/doctrine.php
    doctrine:
        orm:
            event_subscribers:
                - App\EventSubscriber\MigrationSubscriber
    
  2. Custom Migration Commands: Extend the base migration command for project-specific logic:

    namespace App\Command;
    
    use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class CustomMigrateCommand extends MigrateCommand
    {
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            // Custom logic before/after migration
            return parent::execute($input, $output);
        }
    }
    
  3. Service Migrations (v3.7+): Use service-based migrations for complex logic:

    namespace App\Migrations;
    
    use Doctrine\Migrations\AbstractMigration;
    use Doctrine\DBAL\Schema\Schema;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    
    final class Version20230101000000 extends AbstractMigration
    {
        private ContainerInterface $container;
    
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        public function up(Schema $schema): void
        {
            $this->container->get('some.service')->doSomething();
        }
    }
    
  4. Multiple Connections: Configure migrations for multiple Doctrine connections:

    # config/packages/doctrine_migrations.yaml
    doctrine_migrations:
        connections:
            default:
                enabled: true
            secondary:
                enabled: true
                table_storage:
                    table_name: 'migration_versions_secondary'
    

Gotchas and Tips

Pitfalls

  1. Version Control:

    • Never commit migrations to version control after running them in production. Use .gitignore:
      migrations/Versions/*.php
      
    • Exclude the migrations/Versions directory from deployment.
  2. Downgrading Migrations:

    • Downgrade migrations (down() method) must be idempotent. Test thoroughly:
      public function down(SchemaManager $sm, Migration $migration): void
      {
          $this->addSql('DROP TABLE IF EXISTS temp_table');
      }
      
  3. Schema Filtering:

    • Migrations may ignore tables if the schema filter is misconfigured. Verify with:
      php bin/console doctrine:migrations:diff --dry-run
      
  4. Dependency Conflicts:

    • Ensure compatibility with doctrine/doctrine-bundle (e.g., v3.x requires DoctrineBundle 3.0+).
    • Check composer.json for version constraints.
  5. Profiler Overhead:

    • The Symfony Profiler adds overhead to migrations. Disable in production:
      # config/packages/dev/doctrine_migrations.yaml
      doctrine_migrations:
          profiler: false
      

Debugging

  1. Verbose Output: Use --verbose to debug migration execution:

    php bin/console doctrine:migrations:migrate --verbose
    
  2. SQL Logging: Enable Doctrine SQL logging to inspect generated queries:

    # config/packages/dev/doctrine.yaml
    doctrine:
        dbal:
            logging: true
            logging:
                chain:
                    - doctrine: 'single_table_inheritance'
                    - stream: '%kernel.logs_dir%/%kernel.environment%.sql.log'
    
  3. Migration Locking:

    • Migrations use a lock file (migrations.lock) to prevent concurrent runs. Delete this file if stuck:
      rm migrations.lock
      

Tips

  1. Naming Conventions:

    • Use descriptive migration names (e.g., AddUserProfileTable instead of Version20230101000000).
  2. Atomic Migrations:

    • Group related schema changes into a single migration to maintain atomicity.
  3. Testing Migrations:

    • Use PHPUnit to test migrations in isolation:
      use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
      use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
      
      class MigrationTest extends KernelTestCase
      {
          public function testMigration()
          {
              $command = $this->getContainer()->get(MigrateCommand::class);
              $input = new ArrayInput(['command' => 'doctrine:migrations:migrate']);
              $command->run($input, new NullOutput());
          }
      }
      
  4. Custom Storage:

    • Store migration versions in a custom table (e.g., for multi-tenant apps):
      # config/packages/doctrine_migrations.yaml
      doctrine_migrations:
          storage:
              table_storage:
                  table_name: 'migration_versions_custom'
                  version_column_name: 'version'
                  executed_at_column_name: 'executed_at'
      
  5. Post-Migration Hooks:

    • Use postMigration events to trigger actions after migration:
      // src/EventSubscriber/MigrationSubscriber.php
      use Doctrine\Migrations\Event\PostMigrationEventArgs;
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      
      class MigrationSubscriber implements EventSubscriberInterface
      {
          public static function getSubscribedEvents(): array
          {
              return [
                  'migrations.post_migration' => 'onPostMigration',
              ];
          }
      
          public function onPostMigration(PostMigrationEventArgs $args): void
          {
              // Logic after migration
          }
      }
      
  6. Backup Strategy:

    • Always back up the database before running migrations in production.
  7. Rollback Strategy:

    • For critical migrations, implement a rollback plan (e.g., backup tables before dropping them).
  8. Performance:

    • Batch large migrations to avoid timeouts:
      public function up(SchemaManager $sm, Migration $migration): void
      {
          $this->addSql('INSERT INTO users (id, name) VALUES (1, "John"), (2, "Jane")');
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport