【发布时间】:2016-02-20 21:31:38
【问题描述】:
在部署使用 Doctrine ORM 的 Symfony2 应用程序时如何处理迁移?
我一直在使用 DoctrineMigrationsBundle。如果您避免尝试在迁移的 postUp() 部分中使用实体,它会很好地工作。但是,如果这样做,您就会遇到麻烦。
这里有一些伪代码来解释这个问题:
/* Migration1.php */
class Migration1 extends... implements ContainerAwareInterface {
public function up(...) {
query("CREATE TABLE entities WITH COLUMNS col1, col2;");
}
public function postUp(...) {
$e = new Entity();
$e->setCol1("value1");
$e->setCol2("value2");
$entityManager->persist($e);
}
}
/* Migration2.php */
class Migration2 extends... implements ContainerAwareInterface {
public function up(...) {
query("ALTER TABLE entities ADD col3");
}
}
实际案例一:
- 开发人员更改应用程序代码并准备 Migration1
- 代码部署在服务器上,包括运行迁移
- 开发人员更改应用程序代码并准备 Migration2
- 代码部署在服务器上,包括运行迁移
一切正常。
实际案例2:
- 开发人员更改应用程序代码并准备 Migration1
- 开发人员更改应用程序代码并准备 Migration2
- 代码部署在服务器上,包括运行迁移
这不起作用。为什么?
Migration1 的 postUp() 部分中的代码将使用最新的应用程序代码运行。这意味着 Doctrine ORM 将期望 col3 已经存在于实体表中。但是,由于 Migration2 到那时还没有运行,所以没有字段 col3。尝试在 Migration1 中持久化新实体会导致 SQL 错误。
我想出了两个解决这个问题的想法:
- 部署新代码时,使用版本控制系统。分别检查每个提交,在每个提交中运行迁移,直到获得最新的提交或
- 不要使用 postUp() 来更改实体。在完成对数据库的所有结构更改后,在单独的脚本中处理实体。
请就您在该问题上的经验发表评论,并说明您是如何处理它的。我相信你们中的一些人在实践中遇到过这种情况。
【问题讨论】:
-
难道不专门使用 Up() 方法也能解决这个问题吗?
-
并非如此。在某些情况下,您可能希望在应用程序中使用仅在 postUp() 部分中可用的其他服务。
标签: php git entity-framework symfony doctrine-orm