В настоящее время я столкнулся с проблемой миграции с доктриной и моей множественной базой данных (db_name).
У меня есть несколько баз данных внутри одного экземпляра MYSQL: одна для компании, а другая для каждого клиента (сущности).
Каждая база данных создается внутри операции postPersit (я запускаю специальную команду, которая переопределяет базу данных: создание доктрины, чтобы создать базу данных с uuid клиента, это работает).
Я хочу сделать то же самое с миграцией, но вижу ошибку "конфигурация не найдена", и когда я ставлю общую конфигурацию, она не находит того, что ей нужно.
Я создал WrapperConnection и добавил возможность выбора базы данных. Я использую эту оболочку перед запуском запроса платформы API (внутри ApiNormalizer).
Мой код...
#[AsCommand(name: 'custom:migration:migrate')]
final class MigrationCommand extends DoctrineCommand
{
use EntityManagerTrait;
use ParameterBagTrait;
protected function configure(): void
{
$this
->setAliases(['migrate'])
->setDescription(
'Execute a migration to a specified version or the latest available version.',
)
->addArgument(
'name',
InputArgument::REQUIRED,
'The database name'
)
;
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$databaseName = $input->getArgument('name');
if (null === $databaseName) {
// return Command::FAILURE;
}
/** @var MultiDbConnectionWrapper */
$connection = $this->em->getConnection();
$connection->selectDatabase($databaseName);
// Doctrine code is below.
$migrateCmd = new DoctrineMigrateCommand($this->getDependencyFactory());
$migrateInput = new ArrayInput([
'--configuration' => $this->parameterBag->get('kernel.project_dir').'/config/packages/doctrine.yaml',
]);
$migrateCmd->run($migrateInput, $output);
}
}
Я попытался скопировать/вставить напрямую код класса, чтобы отредактировать его... Мне это не удалось...
Я хочу использовать миграцию по динамической схеме, но я новичок в коде доктрины и миграции. Вы можете мне помочь ?
Если бы я знал, как работает конфигурация, я мог бы создать копии файлов миграции с хорошей схемой, я думаю, и запустить ее... что вы думаете?
Извините за мой приблизительный английский.




Я нашел это.
Вот решение
<?php
namespace App\Command\Doctrine;
use App\Service\Trait\ParameterBagTrait;
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand as DoctrineMigrateCommand;
use Symfony\Component\Console\Attribute\AsCommand;
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\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Yaml;
// the name of the command is what users type after "php bin/console"
#[AsCommand(name: 'alx:migration:migrate', aliases: ['alx:mi:mi', 'alx-migrate'])]
final class MigrationCommand extends Command
{
use ParameterBagTrait;
protected function configure(): void
{
$this
->setAliases(['migrate'])
->setDescription(
'Execute a migration on a specific database',
)
->addArgument(
'name',
InputArgument::REQUIRED,
'The database name'
)
;
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$databaseName = $input->getArgument('name');
if (null === $databaseName) {
return Command::FAILURE;
}
// Create the tmp file.
$dbPath = $this->getDatabaseConfigPath($databaseName);
$migrationPath = $this->getMigrationConfigPath();
$migrateCmd = new DoctrineMigrateCommand();
$migrateInput = new ArrayInput([
'--db-configuration' => $dbPath,
'--configuration' => $migrationPath,
]);
// I dont want it to ask the question.
$migrateInput->setInteractive(false);
// execute the migration.
$migrateCmd->run($migrateInput, $output);
// Delete the tmp file.
unlink($dbPath);
unlink($migrationPath);
return 0;
}
public function getDatabaseConfigPath(string $dbName): string
{
$urlDb = $this->parameterBag->get('database_url');
$url = str_replace('bastion', $dbName, $urlDb);
$phpContent = "<?php return ['url' => '$url']; ?>";
return $this->createTmpFile('db_'.$dbName.'_'.uniqid().'.php', $phpContent);
}
public function getMigrationConfigPath(): string
{
/** @var string $directory */
$directory = $this->parameterBag->get('kernel.project_dir');
$migrationPath = $directory.'/migrations';
$content = Yaml::dump([
'migrations_paths' => [
'DoctrineMigrations' => $migrationPath,
],
'table_storage' => [
'table_name' => 'doctrine_migration_versions',
'version_column_name' => 'version',
'version_column_length' => '191',
],
]);
$name = uniqid('migration_');
return $this->createTmpFile($name.'.yaml', $content);
}
private function createTmpFile(string $filename, string $content): string
{
$filesystem = new Filesystem();
$tempFilePath = sys_get_temp_dir().'/'.$filename;
$filesystem->dumpFile($tempFilePath, $content);
return $tempFilePath;
}
}
файл базы данных
<?php
return [
'url' => 'mysql://USER:PWD@database:3306/myDatabaseName?serverVersion=10.5.15-MariaDB&charset=utf8mb4'
];
Файл миграции (yaml)
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '/app/migrations'
table_storage:
table_name: 'doctrine_migration_versions'
version_column_name: 'version'
version_column_length: '191'
@loicfavory Я заменил код на последнюю версию.
Привет, не могли бы вы отредактировать свой ответ, чтобы отобразить содержимое метода getTmpDatabaseFile?