首页 > 解决方案 > 如何在 symfony 4 中自动生成数据库

问题描述

我正在尝试使用 Symfony 4 自动创建一个数据库。在表单中为我的数据库定义一个名称就足够了,然后我的控制器(或服务)自动创建具有该名称的数据库以及所有具有已创建实体的表.

我正在使用 Symfony 4.2 和 Mysql 5.7

我的学说.yaml

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                url: '%env(resolve:DATABASE_URL)%default'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
            customer1:
                url: '%env(resolve:DATABASE_URL)%customer1'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
            customer2:
                url: '%env(resolve:DATABASE_URL)%customer2'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci

    orm:
        auto_generate_proxy_classes: true
        default_entity_manager: gomyclic
        entity_managers:
            default:
                connection: default
                mappings:
                    Main:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Main'
                        prefix: 'App\Entity\Main'
                        alias: Main
            customer1:
                connection: customer1
                mappings:
                    Customer1:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: Customer1
            customer2:
                connection: customer2
                mappings:
                    Customer2:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: Customer2

.env 中的 DATABASE_URL 变量

DATABASE_URL=mysql://dbuser:dbsecret@127.0.0.1:3306/

以及我的控制器中的实际代码 修改教义.yaml 文件的部分

use Symfony\Component\Yaml\Yaml;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;

        $path = __DIR__ . '/../../config/packages/doctrine.yaml';
        $database_name = 'mydatabase';
        $file = Yaml::parseFile($path);
        $dbal = [
            "url" => sprintf("%%env(resolve:DATABASE_URL)%%%s", strtolower($database_name)),
            "driver" => "pdo_mysql",
            "server_version" => "5.7",
            "charset" => "utf8mb4",
            "default_table_options" => [
                "charset" => "utf8mb4",
                "collate" => "utf8mb4_unicode_ci"
            ]
        ];
        $orm = [
            "connection" => strtolower($database_name),
            "mappings" => [
                ucfirst(strtolower($database_name)) =>  [
                    "is_bundle" => false,
                    "type" => "annotation",
                    "dir" => "%kernel.project_dir%/src/Entity",
                    "prefix" => "App\Entity",
                    "alias" => ucfirst(strtolower($database_name)),
                ]
            ]
        ];
        $file['doctrine']['dbal']['connections'][strtolower($database_name)] = $dbal;
        $file['doctrine']['orm']['entity_managers'][strtolower($database_name)] = $orm;
        $yaml = Yaml::dump($file, 8);
        file_put_contents($path, $yaml);

以及应该创建数据库并用表来完成它的部分

        $application = new Application($kernel);
        $application->setAutoExit(false);
        $input = new ArrayInput([
            'command' => 'doctrine:database:create',
            '--connection' => strtolower($database_name)
        ]);
        $output = new BufferedOutput();
        $application->run($input, $output);
        $content = $output->fetch();

        $application = new Application($kernel);
        $application->setAutoExit(false);
        $input = new ArrayInput([
            'command' => 'doctrine:schema:create',
            '--em' => strtolower($database_name)
        ]);
        $output = new BufferedOutput();
        $application->run($input, $output);
        $content = $output->fetch();

这样我们就可以在同一个 symfony 应用程序上创建多个数据库,同时可以创建新的数据库,而不必手动编辑教义.yaml 文件来创建新的 dbal 和 orm。

通过运行现在的代码,我得到了这两个错误:

Error thrown while running command
"doctrine:database:create --connection=mydatabase"
. Message:
"Doctrine ORM Connection named "mydatabase" does not exist."
Error thrown while running command
"doctrine:schema:create --em=mydatabase"
. Message:
"Doctrine ORM Manager named "mydatabase" does not exist."

通过在互联网上寻找解决方案,我知道我必须重新初始化容器,但我没有找到针对我的特殊情况的方法,我希望有另一种方法可以使用 Symfony4 和 Doctrine 完成这项工作。

标签: symfony4

解决方案


您已创建 3 个数据库连接:

  • 默认
  • 客户1
  • 客户2

错误消息显示“mydatabase”不存在。确实它没有配置。教义:数据库:创建在您的教义.yaml 中查找配置。

因此,您必须动态更改配置,这是一个巨大的安全漏洞。

您的用例看起来非常适合docker设置。使用 docker,您可以创建具有所需功能的基础映像,然后为新数据库创建新的 dockerfile,然后启动新容器。

对于每个容器中的启动脚本,可能有一个 sql 脚本,它可以根据需要通过学说迁移来初始化所有表。


推荐阅读