我们正在使用学说迁移,当迁移包含多个动作并且其中一个失败时,通常会出现问题。

例如,如果有一个迁移添加5个外键,而其中的第五键失败,而字段的长度不相同,则将错误和再生迁移的错误解决。 不是 修复整个过程,虽然现在已经存在一个错误的键已经存在的错误,并且不允许迁移成功运行。

是否有一种稳定的方法来使用学说迁移,而没有提到的明显问题?我们已经使用过 .sql 文件预处理,实际上并没有好多了,但是我很确定有 正确的 使用学说项目的数据库版本控制方式?

基于模型和模式之间的差异生成迁移是很棒的,我想保留这种可能性。

谢谢

有帮助吗?

解决方案

我有点解决了这个问题,解决方案并不是那么好,但是我想这对他人很有用。我确实使用CLI确实已经完成了该文件,使每个迁移都更新数据库中的数字,类似于提出此问题之前Timo答案中的数字,但这仍然不是很有效,但无论如何还是值得做的。

我接下来做了什么解决问题,转到doctrine/lib/Doctrine/Migration/Builder.php 第531行。有默认类的定义每个迁移将扩展。由于我正在使用CLI,但找不到将参数传递到这个地方的方法 Doctrine_Migration_Base 去另一堂课 MY_Doctrine_Migration_Base 在下面。

如果您不使用CLI,我会说您应该尝试通过选项而不替换源。

因此下层班级扩展 Doctrine_Migration_Base 并向这些方法覆盖一堆方法,检查是否可以进行更改,然后调用父方法进行操作。它没有涵盖当前的所有方法,只是我写这本书时遇到的那些方法。

现在,每个迁移学说都会创建我的班级,旨在防止我最初提到的问题。

<?php

class MY_Doctrine_Migration_Base extends Doctrine_Migration_Base {
    public function __construct() {
        $this->connection = Doctrine_Manager::getInstance()->getCurrentConnection();
    }

    public function addIndex($tableName, $indexName, array $definition) {
        foreach ($this->connection->execute("SHOW INDEXES IN $tableName")->fetchAll(PDO::FETCH_ASSOC) as $index) {
            if ($index['Key_name'] === $indexName.'_idx') {
                echo "Index $indexName already exists in table $tableName. Skipping\n";
                return;
            }
        }

        parent::addIndex($tableName, $indexName, $definition);
    }

    public function removeColumn($tableName, $columnName) {
        if ($this->column_exists($tableName, $columnName)) {
            parent::removeColumn($tableName, $columnName);
        } else {
            echo "Column $columnName doesn't exist in $tableName. Can't drop\n";
        }
    }

    public function createTable($tableName, array $fields = array(), array $options = array()) {
        if ($this->connection->execute("SHOW TABLES LIKE '$tableName'")->fetchAll(PDO::FETCH_ASSOC)) {
            echo "Table $tableName already exists. Can't create\n";
        } else {
            parent::createTable($tableName, $fields, $options);
        }
    }

    public function addColumn($tableName, $columnName, $type, $length = null, array $options = array()) {
        if (! $this->column_exists($tableName, $columnName)) {
            parent::addColumn($tableName, $columnName, $type, $length, $options);
        } else {
            echo "Column $columnName already exists in $tableName. Can't add\n";
        }
    }

    private function column_exists($tableName, $columnName) {
        $exception = FALSE;

        try { //parsing information_schema sucks because security will hurt too bad if we have access to it. This lame shit is still better
            $this->connection->execute("SELECT $columnName FROM $tableName")->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $exception) {}
        //if someone knows how to check for column existence without exceptions AND WITHOUT INFORMATION SCHEMA please rewrite this stuff

        return $exception === FALSE;
    }
}

欢迎有关如何改进的建议。

其他提示

如果您使用的是学说-CLI,则可以编写自己的迁移任务,该任务在迁移之前备份数据库,并在迁移失败时恢复备份。我为我们的符合/学说迁移写了类似的东西。

如果将任务类放在正确的目录中,学说CLI将其显示在可用命令列表中

学说迁移无法处理。很遗憾地说我们都有这些问题,因为迁移没有在交易中进行。

您可以通过添加插件来改进它。看: 博客台

另一种可能性是在迁移之前进行数据库备份,如果出现问题,则可以重新安装备份。您可以通过shell脚本自动化此功能

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top