Skip to content

Instantly share code, notes, and snippets.

@marcelkorpel
Created February 3, 2021 12:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcelkorpel/5fcb11f04ba460f25aaac1e79f89134e to your computer and use it in GitHub Desktop.
Save marcelkorpel/5fcb11f04ba460f25aaac1e79f89134e to your computer and use it in GitHub Desktop.
Migrations with multiple entity managers
<?php
namespace App\Command\Migrations;
use Doctrine\Migrations\Configuration\EntityManager\ExistingEntityManager;
use Doctrine\Migrations\Configuration\Migration\YamlFile;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class DiffCommand extends Command
{
private ManagerRegistry $registry;
public function __construct(ManagerRegistry $registry)
{
parent::__construct();
$this->registry = $registry;
}
protected function configure(): void
{
$this
->setName('app:migrations:diff')
->setDescription('Proxy to launch doctrine:migrations:diff command as it would require a "configuration" option, and we can\'t define em/connection in config.')
->addArgument('em', InputArgument::REQUIRED, 'Name of the Entity Manager to handle.')
->addArgument('version', InputArgument::OPTIONAL, 'The version number (YYYYMMDDHHMMSS) or alias (first, prev, next, latest) to migrate to.', 'latest')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute the migration as a dry run.')
->addOption('query-time', null, InputOption::VALUE_NONE, 'Time all the queries individually.')
->addOption('allow-no-migration', null, InputOption::VALUE_NONE, 'Don\'t throw an exception if no migration is available (CI).')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$newInput = new ArrayInput([]);
$newInput->setInteractive($input->isInteractive());
$otherCommand = new \Doctrine\Migrations\Tools\Console\Command\DiffCommand($this->getDependencyFactory($input));
$otherCommand->run($newInput, $output);
return 0;
}
private function getDependencyFactory(InputInterface $input): DependencyFactory
{
$em = $this->registry->getManager($input->getArgument('em'));
$config = new YamlFile(__DIR__ . '/../../../config/doctrine_migrations/' . $input->getArgument('em') . '.yaml');
return DependencyFactory::fromEntityManager($config, new ExistingEntityManager($em));
}
}
# /config/packages/doctrine.yaml
doctrine:
dbal:
connections:
user:
driver: 'pdo_mysql'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
url: '%env(resolve:DATABASE_URL_USER)%'
foo:
driver: 'pdo_mysql'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
url: '%env(resolve:DATABASE_URL_FOO)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '13'
orm:
auto_generate_proxy_classes: true
default_entity_manager: foo
entity_managers:
user:
connection: user
mappings:
User:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/User'
prefix: 'App\Entity\User'
alias: User
foo:
connection: foo
mappings:
Foo:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Foo'
prefix: 'App\Entity\Foo'
alias: Foo
# /config/packages/doctrine_migrations.yaml
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations'
em: foo
<?php
namespace App\Command\Migrations;
use Doctrine\Migrations\Configuration\EntityManager\ExistingEntityManager;
use Doctrine\Migrations\Configuration\Migration\YamlFile;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class MigrateCommand extends Command
{
private ManagerRegistry $registry;
public function __construct(ManagerRegistry $registry)
{
parent::__construct();
$this->registry = $registry;
}
protected function configure(): void
{
$this
->setName('app:migrations:migrate')
->setDescription('Proxy to launch doctrine:migrations:migrate command as it would require a "configuration" option, and we can\'t define em/connection in config.')
->addArgument('em', InputArgument::REQUIRED, 'Name of the Entity Manager to handle.')
->addArgument('version', InputArgument::OPTIONAL, 'The version number (YYYYMMDDHHMMSS) or alias (first, prev, next, latest) to migrate to.', 'latest')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute the migration as a dry run.')
->addOption('query-time', null, InputOption::VALUE_NONE, 'Time all the queries individually.')
->addOption('allow-no-migration', null, InputOption::VALUE_NONE, 'Don\'t throw an exception if no migration is available (CI).')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$newInput = new ArrayInput([
'version' => $input->getArgument('version'),
'--dry-run' => $input->getOption('dry-run'),
'--query-time' => $input->getOption('query-time'),
'--allow-no-migration' => $input->getOption('allow-no-migration'),
]);
$newInput->setInteractive($input->isInteractive());
$otherCommand = new \Doctrine\Migrations\Tools\Console\Command\MigrateCommand($this->getDependencyFactory($input));
$otherCommand->run($newInput, $output);
return 0;
}
private function getDependencyFactory(InputInterface $input): DependencyFactory
{
$em = $this->registry->getManager($input->getArgument('em'));
$config = new YamlFile(__DIR__ . '/../../../config/doctrine_migrations/' . $input->getArgument('em') . '.yaml');
return DependencyFactory::fromEntityManager($config, new ExistingEntityManager($em));
}
}
# /config/doctrine_migrations/user.yaml
# add as many configuration files as there are entity managers
migrations_paths:
'Migrations\UserMigrations': 'migrations/User'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment