8

I have 2 databases db1 and db2 in symfony2 + doctrine2 and both databases are different from each other in terms of tables and their fields.

I need to work on migration. Things work fine as long as there is one database.

But it does not works when there are more than one databases.

Also, is there any way where I can provide entity manager specific migration settings.

Or is there any way through which I can provide connection or entity manager in the migration class.

yivi
  • 42,438
  • 18
  • 116
  • 138
Ajinder Singh
  • 89
  • 1
  • 3

5 Answers5

16

You can provide an entityManager using --em=name option in the migration task. I also add this piece of code, to avoid executing of the migration on another db by mistake:

    $parameters = $this->connection->getParams();
    $this->skipIf(
        $parameters['dbname'] != "my_db_name"
        'This is the other DB\'s migration, pass a correct --em parameter'
    );

I haven't found any other way to check the EM, so I can't help you if your databases have same names.

Also note, that you should add the skipIf to all your migrations, so you can migrate without worry in both you databases.

wdev
  • 2,190
  • 20
  • 26
  • 2
    The only problem I found with this approach is that if you use different db names on development, test, staging and production you have to add multiple conditions. It would be easier if we could have access to the entityManager parameter. – Sergi Nov 29 '11 at 16:35
10

This question is a little old, but it came up first when I was asking the same thing. I found my answer in the Doctrine migrations configuration docs. Let's say you have connections for two databases, each with their own entity managers (mapped here with XML, not annotations, and not auto mapped so the schema configs can live in the same config/doctrine path):

# config.yml
doctrine:
dbal:
    default_connection: default
    connections:
        default:
            driver: '%database_driver%'
            ...
        special:
            driver: '%special_database_driver%'
orm:
    entity_managers:
        default:
            auto_mapping: false
            mappings:
                base:
                    type: xml
                    dir: '%kernel.root_dir%/../src/MyBundle/Resources/config/doctrine/base'
                    prefix: MyBundle\Entity
                    alias: Base
                    is_bundle: false
        special:
            auto_mapping: false
            connection: special
            mappings:
                special:
                    type: xml
                    dir: '%kernel.root_dir%/../src/MyBundle/Resources/config/doctrine/special'
                    prefix: MyBundle\Special
                    alias: Special
                    is_bundle: false

Then you do not include the doctrine_migrations configurations in config.yml. Instead, create a configuration file for each one:

# src/MyBundle/Resources/config/migrations/base.yml
name: BaseMigrations
migrations_namespace: MyBundle\Migrations\Base
table_name: Migrations
migrations_directory: src/MyBundle/Migrations/Base

# src/MyBundle/Resources/config/migrations/special.yml
name: SpecialMigrations
migrations_namespace: MyBundle\Migrations\Special
table_name: Migrations
migrations_directory: src/MyBundle/Migrations/Special

Then, whenever you run any migration command, specify both the entity manager and configuration:

bin/console doctrine:migrations:status --env=dev --em=special --configuration=src/MyBundle/Resources/config/migrations/special.yml

It's a bit to remember if running by hand, so you might want to wrap them up in your own command to make life easy (e.g. something like bin/console my:migrations:status --env=dev --db=special). It's also not an issue if you have a deploy bash script, like:

#!/bin/bash
ENVIRONMENT="$1"

# Run migrations for a configuration
function runMigrations()
{
    local CONFIG="$1"
    local MANAGER="$2"
    local STATUS="$(bin/console doctrine:migrations:status --env=${ENVIRONMENT} --configuration=${CONFIG} --em=${MANAGER})"

    case "${STATUS}" in
        *"Already at latest version"*)
            # Do nothing
            ;;
        *)
            runNextMigration $CONFIG $MANAGER
            ;;
    esac
}

# Run the next migration for a configuration
function runNextMigration()
{
    local CONFIG="$1"
    local MANAGER="$2"
    bin/console doctrine:migrations:migrate next --env=$ENVIRONMENT --configuration=$CONFIG --em=$MANAGER

    runMigrations $CONFIG $MANAGER
}

runMigrations "src/MyBundle/Resources/config/migrations/base.yml" "default"
runMigrations "src/MyBundle/Resources/config/migrations/special.yml" "special"
iisisrael
  • 583
  • 6
  • 6
1

I've been using @iisisrael's answer for years. But after upgrading to doctrine/migrations 3.x I had to change the format of the config files. This is what I have now:

# config/packages/migrations/base.yaml
em: default
transactional: false
migrations_paths:
    Hyra\Migrations\Base: src/Migrations/Base
table_storage:
    table_name: migration_versions
# config/packages/migrations/special.yaml
em: special
transactional: false
migrations_paths:
    App\Migrations\Special: src/Migrations/Special
table_storage:
    table_name: migration_versions

And then I have these in my Makefile so that I don't need to remember the magic incantations:

migrate: migrate-base migrate-special

migrate-base:
    php bin/console doctrine:migrations:migrate --configuration=config/packages/migrations/base.yaml --no-interaction --allow-no-migration

migrate-special:
    php bin/console doctrine:migrations:migrate --configuration=config/packages/migrations/special.yaml --no-interaction --allow-no-migration

diff-migrations-base: migrate
    php bin/console doctrine:migrations:diff --configuration=config/packages/migrations/base.yaml

diff-migrations-special: migrate
    php bin/console doctrine:migrations:diff --configuration=config/packages/migrations/special.yaml
Yep_It's_Me
  • 4,494
  • 4
  • 43
  • 66
0

The similar problem and solution: Symfony2 - Change Migration Directory

You can create another migration folder for second DB and put migrations inside.

Community
  • 1
  • 1
0

I know this is an old threat but it's one of the top Google searches in 2023, this is how I've done it to generate migrations for both MySQL and SQLite with Symfony 6.3 without custom entity managers:

Setup your MySQL in your .env like you would usually do, but set a MIGRATIONS_PATH="migrations/mysql" property to it.

Then create a .env.test and set:

APP_ENV=test
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
MIGRATIONS_PATH="migrations/sqlite"

In your config/packages/doctrine_migrations.yaml you change default path to get from the env files:

doctrine_migrations:
    migrations_paths:
        'DoctrineMigrations': '%kernel.project_dir%/%env(string:MIGRATIONS_PATH)%'
    enable_profiler: false

Also enable MakerBundle for test env in bundles.php:

Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true, 'test' => true],

Now you can generate migrations using:

# for MySQL
php bin/console make:migration
php bin/console doctrine:migration:migrate

# for SQLite
php bin/console make:migration --env=test
php bin/console doctrine:migration:migrate --env=test

Doing this, Symfony will generate migrations for MySQL in migrations/mysql and migrations/sqlite for SQLite.

Rafael
  • 1
  • 1