Skip to content

Instantly share code, notes, and snippets.

@jmsche
Created September 9, 2020 11:14
Show Gist options
  • Save jmsche/2baf98b35eac936b0f6e77378c56f934 to your computer and use it in GitHub Desktop.
Save jmsche/2baf98b35eac936b0f6e77378c56f934 to your computer and use it in GitHub Desktop.
Proxy commands for Doctrine Migrations bundle with multiple entity managers.
<?php
declare(strict_types=1);
namespace App\Command\Migration;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Migrations\Configuration\EntityManager\ExistingEntityManager;
use Doctrine\Migrations\Configuration\Migration\YamlFile;
use Doctrine\Migrations\DependencyFactory;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
abstract class AbstractMigrationCommand extends Command
{
private ManagerRegistry $registry;
public function __construct(ManagerRegistry $registry)
{
parent::__construct();
$this->registry = $registry;
}
protected function configure(): void
{
$this->addArgument('em', InputArgument::REQUIRED, 'Name of the Entity Manager to handle');
}
protected 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));
}
}
<?php
declare(strict_types=1);
namespace App\Command\Migration;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class DiffCommand extends AbstractMigrationCommand
{
protected function configure(): void
{
parent::configure();
$this
->setName('app:migrations:diff')
->setDescription('Wrapper to launch doctrine:migrations:diff command as it would require a "configuration" option')
;
}
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;
}
}
<?php
declare(strict_types=1);
namespace App\Command\Migration;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class GenerateCommand extends AbstractMigrationCommand
{
protected function configure(): void
{
parent::configure();
$this
->setName('app:migrations:generate')
->setDescription('Wrapper to launch doctrine:migrations:generate command as it would require a "configuration" option')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$newInput = new ArrayInput([]);
$newInput->setInteractive($input->isInteractive());
$otherCommand = new \Doctrine\Migrations\Tools\Console\Command\GenerateCommand($this->getDependencyFactory($input));
$otherCommand->run($newInput, $output);
return 0;
}
}
<?php
declare(strict_types=1);
namespace App\Command\Migration;
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;
final class MigrateCommand extends AbstractMigrationCommand
{
protected function configure(): void
{
parent::configure();
$this
->setName('app:migrations:migrate')
->setDescription('Wrapper to launch doctrine:migrations:migrate command as it would require a "configuration" option')
->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;
}
}
<?php
declare(strict_types=1);
namespace App\Command\Migration;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class StatusCommand extends AbstractMigrationCommand
{
protected function configure(): void
{
parent::configure();
$this
->setName('app:migrations:status')
->setDescription('Wrapper to launch doctrine:migrations:status command as it would require a "configuration" option')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$newInput = new ArrayInput([]);
$otherCommand = new \Doctrine\Migrations\Tools\Console\Command\StatusCommand($this->getDependencyFactory($input));
$otherCommand->run($newInput, $output);
return 0;
}
}
<?php
declare(strict_types=1);
namespace App\Command\Migration;
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class SyncMetadataStorageCommand extends AbstractMigrationCommand
{
protected function configure(): void
{
parent::configure();
$this
->setName('app:migrations:sync-metadata-storage')
->setDescription('Wrapper to launch doctrine:migrations:sync-metadata-storage command as it would require a "configuration" option')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$newInput = new ArrayInput([]);
$otherCommand = new SyncMetadataCommand($this->getDependencyFactory($input));
$otherCommand->run($newInput, $output);
return 0;
}
}
<?php
declare(strict_types=1);
namespace App\Command\Migration;
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;
final class VersionCommand extends AbstractMigrationCommand
{
protected function configure(): void
{
parent::configure();
$this
->setName('app:migrations:version')
->setDescription('Wrapper to launch doctrine:migrations:version command as it would require a "configuration" option')
->addArgument('version', InputArgument::OPTIONAL, 'The version to add or delete.', null)
->addOption('add', null, InputOption::VALUE_NONE, 'Add the specified version.')
->addOption('delete', null, InputOption::VALUE_NONE, 'Delete the specified version.')
->addOption('all', null, InputOption::VALUE_NONE, 'Apply to all the versions.')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$newInput = new ArrayInput([
'version' => $input->getArgument('version'),
'--add' => $input->getOption('add'),
'--delete' => $input->getOption('delete'),
'--all' => $input->getOption('all'),
]);
$newInput->setInteractive($input->isInteractive());
$otherCommand = new \Doctrine\Migrations\Tools\Console\Command\VersionCommand($this->getDependencyFactory($input));
$otherCommand->run($newInput, $output);
return 0;
}
}
@MushuLeDragon
Copy link

Hi,
I leave you a comment under your blog post.
I use your solution and add a few commands to complete it. You can fild them on my Gist here.

And I ask you if you can help me to make a custom command to generate migration file dynamically just with the entitymanager name like symfony console custom:make:migration default or symfony console custom:make:migration database_name.

Thanks

@jmsche
Copy link
Author

jmsche commented Mar 17, 2021

Hi @MushuLeDragon,

About your extra commands in your gist (drop & create database if I read correctly) you don't need to create them as the base commands already have this connection option. See eg. https://github.com/doctrine/DoctrineBundle/blob/2.2.x/Command/CreateDatabaseDoctrineCommand.php#L28

About the make:migration command available in the Maker bundle, I think it's only an alias to the migrations:diff command, for which I provide a proxy class in this gist :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment