2011-01-17 2 views
4

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

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

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

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

Thanks

ответ

2

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

То, что я сделал, следующий вид решает вещи, перейдите к doctrine/lib/Doctrine/Migration/Builder.php строка 531. Существует определение класса по умолчанию, при котором каждая миграция будет расширяться. Поскольку я использую CLI и не могу найти способ передать параметры в это место, я только что заменил Doctrine_Migration_Base на другой класс MY_Doctrine_Migration_Base, который ниже.

Если вы не используете CLI, я бы сказал, что вы должны попробовать передать параметры и не заменить источник.

Таким образом, приведенный ниже класс расширяет Doctrine_Migration_Base и перезаписывает кучу методов, проверяя, нормально ли делать изменения, а затем вызывать метод parent для их выполнения. В настоящее время он не охватывает все методы, только те, с которыми я столкнулся, когда я писал это.

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

<?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; 
    } 
} 

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

0

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

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

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

1

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

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

Смежные вопросы