Вопрос

Мы используем миграции доктрины, и часто возникают проблемы, когда миграция содержит несколько действий, и одно из них не удается.

Например, если есть миграция, добавляемая 5 иностранных ключей, а 5 -й из них не сбои, в то время как поля не одинаковой длины, исправляя ошибку с полями и регенерирующими миграциями делает нет Исправьте все это, в то время как теперь возникает ошибка, связанная с фактом 4 ключей уже существует, и не позволяют миграции успешно работать.

Есть ли стабильный способ использовать миграцию доктрины без таких очевидных проблем, как упомянуто? Мы использовали .sql Файлы с прежним, что на самом деле не намного лучше, но я уверен, что есть Правильно Способ версии базы данных для проекта, использующей доктрину?

Генерация миграций на основе разницы между моделями и схемами великолепна, и я хотел бы сохранить эту возможность.

Спасибо

Это было полезно?

Решение

Я как бы решил это, решение не так уж и хорошо, но все же, я думаю, оно будет полезно для других людей. Я действительно использую CLI Действительно, я уже делал файл, в котором каждый миграционный обновление обновляется номер в базе данных, аналогично тому, что в ответе Тимо, прежде чем задать этот вопрос, но это все еще не очень эффективно, но стоит делать в любом случае.

То, что я сделал в следующем, решает вещи, иди в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;
    }
}

Предложения о том, как улучшить это, приветствуются.

Другие советы

Если вы используете Doctrine-Cli, вы можете написать свою собственную задачу миграции, которая поддерживает базу данных перед миграцией и восстанавливает резервную копию, если миграция не удается. Я написал что -то подобное для наших миграций Symfony/Dectrine.

Если вы поместите свой класс задач в правильный каталог, CLI доктрины отобразит его в списке доступных команд

Миграция доктрины не может справиться с этим. Извините, что у всех нас есть эти проблемы, потому что миграция не проходила в сделке.

Вы можете улучшить это, добавив плагин. Видеть: Сообщение блога

Другая возможность состоит в том, чтобы сделать резервную копию базы данных перед мигрированием, и если что -то пойдет не так, вы можете переустановить резервную копию. Вы можете автоматизировать это с помощью сценария оболочки

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top