如何为数据库(特别是Symfony)存储所需的“基础”或“初始”数据?

时间:2022-05-21 07:19:16

I use the doctrine migrations bundle to track changes in my database structure. I would like to ensure that when I'm deploying / adding a new server for my application that:

我使用doctrine迁移包来跟踪数据库结构中的更改。我想确保在为我的应用程序部署/添加新服务器时:

  • (A) the database schema is up to date (doctrine:migrations:migrate)
  • (A)数据库架构是最新的(学说:迁移:迁移)
  • (B) the database always contains a pre-defined set of data
  • (B)数据库始终包含预定义的数据集

For (B) a good example is roles. I want a certain set of roles to always be present. I realize it is possible with database migrations, but I don't like the idea of mixing schema changes with data changes. Also if I use MySql migrations I would have to create a equivalent Sqlite migration for my test database.

对于(B),一个很好的例子是角色。我希望始终存在一组特定的角色。我意识到数据库迁移是可能的,但我不喜欢将模式更改与数据更改混合在一起的想法。此外,如果我使用MySql迁移,我将不得不为我的测试数据库创建一个等效的Sqlite迁移。

Another option I'm aware of is data fixtures. However from reading the documentation I get the feeling that fixtures are more for loading test data. Also if I changed a role name I don't know how that would be updated using fixtures (since they either delete all data in the database before loading or append to it). If I use append then unique keys would also be a problem.

我所知道的另一个选择是数据夹具。然而,通过阅读文档,我感觉夹具更多地用于加载测试数据。此外,如果我更改了角色名称,我不知道如何使用fixture更新它(因为它们要么在加载或附加之前删除数据库中的所有数据)。如果我使用append,那么唯一键也是一个问题。

I'm considering creating some sort of command that takes a set of configuration files and ensures that certain tables are always in a consistent state matching the config files - but if another option exists I'd like to use it of course.

我正在考虑创建一些带有一组配置文件的命令,并确保某些表总是处于与配置文件匹配的一致状态 - 但如果存在另一个选项,我当然希望使用它。

What is the best way to handle loading and managing required data into a database?

处理将所需数据加载到数据库中的最佳方法是什么?

1 个解决方案

#1


2  

If you're using Doctrine Migrations, you can generate initial migration with whole database schema, then you should generate migrations (doctrine:migrations:generate or doctrine:migrations:diff) for all changes that are made in database structure AND also add there queries that will migrate existing data.

如果您正在使用Doctrine Migrations,您可以使用整个数据库模式生成初始迁移,那么您应该为数据库结构中所做的所有更改生成迁移(doctrine:migrations:generate或doctrine:migrations:diff)并添加查询这将迁移现有数据。

Fixtures are designed to pre-populate data (with doctrine:fixtures:load) and, in my opinion, they should be kept up-to-date with latest database schema and executed after doctrine:migrations:migrate / doctrine:schema:create.

Fixtures旨在预先填充数据(使用doctrine:fixtures:load),在我看来,它们应该与最新的数据库模式保持同步,并在doctrine:migrations:migrate / doctrine:schema:create之后执行。

So finally:

最后:

  • Create base migration with initial database schema (instead of executing doctrine:schema:create just generate migration file and migrate it)
  • 使用初始数据库模式创建基本迁移(而不是执行doctrine:schema:create只生成迁移文件并迁移它)
  • Create new migrations for each database schema change AND for migrating existing data (such as role name changing)
  • 为每个数据库模式更改创建新迁移以及迁移现有数据(例如更改角色名称)
  • Keep fixtures up-to-date with latest schema (you can use --append option and only update fixtures instead of deleting all database data first)
  • 使用最新模式使夹具保持最新(您可以使用--append选项并仅更新夹具而不是首先删除所有数据库数据)

Then, when deploying new instance you can run doctrine:schema:create, then doctrine:migrations:version --add --all --no-interaction (mark all migrations as migrated, because you have already created latest schema) and doctrine:fixtures:load which will populate data to the database (also latest version, so data migrations from Doctrine migrations files are not required).

然后,在部署新实例时,您可以运行doctrine:schema:create,然后doctrine:migrations:version --add --all --no-interaction(将所有迁移标记为已迁移,因为您已经创建了最新的模式)和doctrine: fixtures:将数据填充到数据库的load(也是最新版本,因此不需要从Doctrine迁移文件迁移数据)。

Note: Existing instances should NOT use doctrine:schema:update, but only doctrine:migrations:migrate. In our app we even block usage of this command, in app/console:

注意:现有实例不应使用doctrine:schema:update,而应仅使用doctrine:migration:migrate。在我们的应用程序中,我们甚至在app / console中阻止使用此命令:

use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Helper\FormatterHelper;

// Deny using doctrine:schema:update command
if(in_array(trim($input->getFirstArgument()), ['doctrine:schema:update'])) {
    $formatter = new FormatterHelper();
    $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, true);

    $formattedBlock = $formatter->formatBlock(['[[ WARNING! ]]', 'You should not use this command! Use doctrine:migrations:migrate instead!'], 'error', true);

    $output->writeln($formattedBlock);
    die();
}

This is what I figured out from my experience. Hope you will find it useful :-)

这是我从我的经验中得出的结论。希望你会发现它很有用:-)

#1


2  

If you're using Doctrine Migrations, you can generate initial migration with whole database schema, then you should generate migrations (doctrine:migrations:generate or doctrine:migrations:diff) for all changes that are made in database structure AND also add there queries that will migrate existing data.

如果您正在使用Doctrine Migrations,您可以使用整个数据库模式生成初始迁移,那么您应该为数据库结构中所做的所有更改生成迁移(doctrine:migrations:generate或doctrine:migrations:diff)并添加查询这将迁移现有数据。

Fixtures are designed to pre-populate data (with doctrine:fixtures:load) and, in my opinion, they should be kept up-to-date with latest database schema and executed after doctrine:migrations:migrate / doctrine:schema:create.

Fixtures旨在预先填充数据(使用doctrine:fixtures:load),在我看来,它们应该与最新的数据库模式保持同步,并在doctrine:migrations:migrate / doctrine:schema:create之后执行。

So finally:

最后:

  • Create base migration with initial database schema (instead of executing doctrine:schema:create just generate migration file and migrate it)
  • 使用初始数据库模式创建基本迁移(而不是执行doctrine:schema:create只生成迁移文件并迁移它)
  • Create new migrations for each database schema change AND for migrating existing data (such as role name changing)
  • 为每个数据库模式更改创建新迁移以及迁移现有数据(例如更改角色名称)
  • Keep fixtures up-to-date with latest schema (you can use --append option and only update fixtures instead of deleting all database data first)
  • 使用最新模式使夹具保持最新(您可以使用--append选项并仅更新夹具而不是首先删除所有数据库数据)

Then, when deploying new instance you can run doctrine:schema:create, then doctrine:migrations:version --add --all --no-interaction (mark all migrations as migrated, because you have already created latest schema) and doctrine:fixtures:load which will populate data to the database (also latest version, so data migrations from Doctrine migrations files are not required).

然后,在部署新实例时,您可以运行doctrine:schema:create,然后doctrine:migrations:version --add --all --no-interaction(将所有迁移标记为已迁移,因为您已经创建了最新的模式)和doctrine: fixtures:将数据填充到数据库的load(也是最新版本,因此不需要从Doctrine迁移文件迁移数据)。

Note: Existing instances should NOT use doctrine:schema:update, but only doctrine:migrations:migrate. In our app we even block usage of this command, in app/console:

注意:现有实例不应使用doctrine:schema:update,而应仅使用doctrine:migration:migrate。在我们的应用程序中,我们甚至在app / console中阻止使用此命令:

use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Helper\FormatterHelper;

// Deny using doctrine:schema:update command
if(in_array(trim($input->getFirstArgument()), ['doctrine:schema:update'])) {
    $formatter = new FormatterHelper();
    $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, true);

    $formattedBlock = $formatter->formatBlock(['[[ WARNING! ]]', 'You should not use this command! Use doctrine:migrations:migrate instead!'], 'error', true);

    $output->writeln($formattedBlock);
    die();
}

This is what I figured out from my experience. Hope you will find it useful :-)

这是我从我的经验中得出的结论。希望你会发现它很有用:-)