Doctrine 动态架构迁移(在特定数据库上)

问题描述 投票:0回答:1

我目前面临着学说和我的多个数据库(db_name)的迁移问题


我在同一个 MYSQL 实例中有多个数据库,一个用于公司,另一个用于每个客户端(实体)。

每个数据库都是在 postPersit 操作中创建的(我正在运行覆盖数据库的自定义命令:create ofdoctrine 以使用客户端的 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);
     }
}

我尝试直接复制/粘贴类的代码来编辑它......我失败了......

我想在动态模式上使用迁移,但我对原则代码和迁移很陌生。 你能帮我吗?


如果我知道配置是如何工作的,我可以使用我认为良好的模式创建迁移文件的副本并运行它......你觉得怎么样?

抱歉我的英语近似。

symfony doctrine migration
1个回答
0
投票

我找到了。

解决方案在这里

<?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'

© www.soinside.com 2019 - 2024. All rights reserved.