Доктрина миграции запасной
-
11-10-2019 - |
Вопрос
Мы используем миграции доктрины, и часто возникают проблемы, когда миграция содержит несколько действий, и одно из них не удается.
Например, если есть миграция, добавляемая 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 доктрины отобразит его в списке доступных команд
Миграция доктрины не может справиться с этим. Извините, что у всех нас есть эти проблемы, потому что миграция не проходила в сделке.
Вы можете улучшить это, добавив плагин. Видеть: Сообщение блога
Другая возможность состоит в том, чтобы сделать резервную копию базы данных перед мигрированием, и если что -то пойдет не так, вы можете переустановить резервную копию. Вы можете автоматизировать это с помощью сценария оболочки