For development we have a single Symfony console command that executes other console commands in order to rebuild db, run fixtures etc.
As part of the process I need to run a few cherry-picked doctrine migration commands, but for some reason I'm unable to run multiple execute commands within the same process.
To confirm, I can run these tasks without issue manually, and can run one of either command within the console execute and then the other manually without issue.
$this->getApplication()->run(new ArrayInput(array(
'command' => 'doctrine:migrations:execute',
'version' => '20140310162336',
'--no-interaction' => true
)), $output);
$this->getApplication()->run(new ArrayInput(array(
'command' => 'doctrine:migrations:execute',
'version' => '20140310170437',
'--no-interaction' => true
)), $output);
The error returned is:
[Doctrine\DBAL\Migrations\MigrationException]
Migration version 20140310162334 already registered with class Doctrine\DBAL\Migrations\Version
The version being the first version file that exists, can confirm that one is not in the migration_versions table, nor is it wanted in this scenario. Suggesting it is just loaded into the migrations object.
Can anyone offer input if I'm doing something wrong of if this is perhaps a bug somewhere.
Running Symfony 2.2.* and migrations bundle using dev-master.
I had the same problem on symfony 2.6 and the solution described by Alexei Tenitski didn't work althought it seemed a valid one. This is the solution that worked for me.
/**
* Loop thorugh the config and path config for migrations
* and execute migrations for each connection
*/
foreach (array_keys($this->migrationsConfig) as $configEm) {
if (
(empty($ems) || in_array($configEm, $ems))
&& !in_array($configEm, $ignoreEms)
) {
try {
// new instance of the command you want to run
// to force reload MigrationsConfig
$command = new MigrateSingleCommand($this->migrationsConfig);
$command->setApplication($this->getApplication());
$arguments = [
'command' => $commandString,
'--em' => $configEm,
];
$input = new ArrayInput($arguments);
$command->run($input, $output);
} catch (\Exception $e) {
$output->writeln(sprintf("<error>Error: %s</error>", $e->getMessage()));
}
}
}
if you use $this->getApplication()->run()
it will take the command from $this->application->commands
where the commands are initialized only once and (when the command calling is initialized) so the MigrationsConfig will stay the same on all iterations.
The problem is that application uses same instance of command for each call and Doctrine migrate commands are not designed to work in such environment. One way to work around it is to clone command and work with its instance directly:
$commandName = 'doctrine:migrations:execute';
$prototypeCommand = $this->getApplication()->get($commandName);
// This is required to avoid merging of application definition for each cloned command
$prototypeCommand->mergeApplicationDefinition();
// Create a clone for a particular run
$command1 = clone $prototypeCommand;
// Run the command with specific params
$command1->run($input1, $output)
// Create another clone
$command2 = clone $prototypeCommand;
// Run the command with another set of params
$command2->run($input2, $output)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With