教義の移行フォールバック
-
11-10-2019 - |
質問
私たちは教義の移行を使用していますが、移行に複数のアクションが含まれており、そのうちの1つが失敗した場合、多くの場合問題があります。
たとえば、5つの外部キーを追加する移行があり、そのうちの5番目がフィールドが同じ長さではない間に失敗すると、フィールドでエラーを修正し、移行を再生する いいえ 全体を修正しますが、今ではキーの4つの事実に関連するエラーが既に存在し、移行が正常に実行されないようにしています。
言及されているような明らかな問題なしに、教義の移行を使用する安定した方法はありますか?使用しました .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;
}
}
これを改善する方法に関する提案は大歓迎です。
他のヒント
Doctrine-CLIを使用している場合は、移行前にデータベースをバックアップする独自の移行タスクを作成し、移行が失敗した場合にバックアップを復元することができます。私は、私たちのSymfony/Doctrine Migrationsに似たようなものを書きました。
タスククラスを正しいディレクトリに配置すると、DoctrineCLIが利用可能なコマンドのリストに表示されます
教義の移行はこれを処理できません。移行がトランザクションで実行されなかったため、私たち全員がこれらの問題を抱えていると言って申し訳ありません。
プラグインを追加することでこれを改善できます。見る: ブログポスト
もう1つの可能性は、移行する前にデータベースバックアップを行うことです。何か問題が発生した場合は、バックアップを再インストールできます。これをシェルスクリプトで自動化できます