Weave 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

The Doctrine Migrations Bundle integrates the Doctrine Migrations library into Symfony, adding console commands and configuration to generate, version, run, and roll back database schema migrations. It supports multiple entity managers and connections for managing migrations across complex apps.

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.
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo
bernskioldmedia/laravel-harvest
bernskiold/laravel-data-scrubber
bernskiold/laravel-currency-converter
bernskiold/laravel-campaign-monitor
bernskioldmedia/laravel-autotranslate
siberfx/telegram-bot
roy-sandip/laravel-view-extended
gregsphotography/site-builder-core
roy-sandip/laravel-view
anodyne/blade-fluentui-icons
webx-ui/module-catalog-collections