php - 学说迁移 : How to avoid SQL errors in the postUp step?

标签 php git entity-framework symfony doctrine-orm

在部署使用 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() 来更改实体。在完成对数据库的所有结构更改后,在单独的脚本中处理实体。

请评论您在此问题上的经历并说明您是如何处理的。我相信你们中的一些人在实践中遇到过这种情况。

最佳答案

您描述的场景完美地表明(通常)不可能在 Doctrine Migrations 中使用实体。

因此,恐怕使这项工作以稳健的方式进行的唯一方法是降到 DBAL 级别:

public function postUp(...) {
    $this->connection->insert('entities', [
        'col1' => 'value1',
        'col2' => 'value2'
    ]);
}

通过使用 DBAL 查询,将直接提供要使用的列,而不是通过应用程序代码定义的实体间接提供,不需要与当前表结构同步。

另见 "How to work with Doctrine migrations in Symfony" post 的第 4.2 节,它也描述了在 Doctrine Migrations 中使用实体的这个问题,尤其是下面的引用:

don't use entities within migrations, you must not rely on the entity (PHP) code, but on the database only!

关于php - 学说迁移 : How to avoid SQL errors in the postUp step?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35529309/

相关文章:

php - 甜蜜警报(我想更新数据库状态(默认 :pending) into confirm when i click sweet alert confirm button

php - 我可以获取最初在包含文件中调用的 PHP 文件的路径吗?

php - 如何获取 php 数组中的前 3 个值及其索引

php - MySQL多表中使用checkbox选择数据并根据checkbox显示表字段

git - 如何排除带有 "git diff"的补丁 header ?

python - 为什么我不应该将 virtualenv 推送到 Heroku?

Git Woes : edited on windows, 现在在 Linux 上有问题

c# - 如何从配置文件禁用 Entity Framework 中的缓存

c# - Entity Framework 代码优先多列外键

c# - 安全访问部分属性