如何存储数据库(特别是Symfony)所需的“基本”或“初始”数据? [英] How can I store required 'base' or 'initial' data for a database (in particular Symfony)?
问题描述
我使用doctrine迁移软件包跟踪我的数据库结构中的更改。我想确保当我为我的应用程序部署/添加一个新的服务器:
- (A)数据库模式(doctrine:migrations:migrate)
- (B)数据库始终包含预定义的数据集
对于(B)一个好的例子是角色。我想要一组特定的角色总是存在。我意识到这是可能与数据库迁移,但我不喜欢混合模式更改与数据更改的想法。如果我使用MySql迁移,我将不得不为我的测试数据库创建一个等效的Sqlite迁移。
我知道的另一个选项是数据夹具。然而从阅读文档我得到的感觉,夹具更多的加载测试数据。此外,如果我更改了一个角色名称,我不知道如何更新使用fixtures(因为它们删除数据库中的所有数据加载或附加之前)。如果我使用append然后唯一的键也将是一个问题。
我正在考虑创建某种命令,该命令需要一组配置文件,并确保某些表始终处于与配置文件匹配的一致状态 - 但如果另一个选项存在我想要使用它当然。
处理加载和管理数据库中所需数据的最好方法是什么?
如果您使用Doctrine Migrations,您可以使用整个数据库模式生成初始迁移,那么您应该生成迁移( doctrine:migrations:generate
code> doctrine:migrations:diff )用于数据库结构中的所有更改,并添加将迁移现有数据的查询。
灯具设计用于预填充数据(使用 doctrine:fixtures:load
),在我看来,它们应该保持最新的最新数据库模式并在 doctrine:migrations:migrate
/ / doctrine:schema:create
/ p>
最后:
- 使用初始数据库模式创建基本迁移
doctrine:schema:create
只是生成迁移文件并将其迁移) - 为每个数据库模式更改创建新迁移并迁移现有数据(例如更改角色名称)
- 使用最新模式保持装置最新状态(您可以使用
- 附加
选项,只需更新fixture,而不是先删除所有数据库数据)
然后,在部署新实例时,您可以运行 doctrine :schema:create
,然后 doctrine:migrations:version --add --all --no-interaction
(将所有迁移标记为已迁移,因为您已经创建了最新的模式)和 doctrine:fixtures:load
,它将数据填充到数据库(也是最新版本,因此不需要从Doctrine迁移文件迁移数据)。
注意:现有实例不应使用 doctrine:schema:update
doctrine:migrations:migrate
。在我们的应用程序中,我们甚至在 app / console
中阻止使用此命令:
use Symfony\Component\Console\Output\ConsoleOutput;
使用Symfony\Component\Console\Helper\FormatterHelper;
//拒绝使用doctrine:schema:update命令
if(in_array(trim($ input-> getFirstArgument()),['doctrine:schema:update'
$ formatter = new FormatterHelper();
$ output = new ConsoleOutput(ConsoleOutput :: VERBOSITY_NORMAL,true);
$ formattedBlock = $ formatter-> formatBlock(['[[WARNING!]]','你不应该使用这个命令!use doctrine:migrations:migrate instead!'],'error' ,true);
$ output-> writeln($ formattedBlock);
die();
}
这是我从我的经验中得出的。希望你会发现它有用: - )
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:
- (A) the database schema is up to date (doctrine:migrations:migrate)
- (B) the database always contains a pre-defined set of data
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.
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.
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?
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.
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
.
So finally:
- Create base migration with initial database schema (instead of executing
doctrine:schema:create
just generate migration file and migrate it) - 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)
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).
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
:
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 :-)
这篇关于如何存储数据库(特别是Symfony)所需的“基本”或“初始”数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!