2011-01-17 11 views
4

Wir verwenden Doktrin-Migrationen, und es gibt häufig Probleme, wenn die Migration mehrere Aktionen enthält und eine davon fehlschlägt.Migrationen von Dokumentinformationen

Wenn beispielsweise eine Migration 5 Fremdschlüssel hinzufügt und der fünfte von ihnen fehlschlägt, während die Felder nicht die gleiche Länge haben, wird der Fehler mit den Feldern behoben und die Migrationen neu erstellt nicht Es besteht jedoch ein Fehler, der damit zusammenhängt, dass 4 der Schlüssel bereits vorhanden sind und die Migration nicht erfolgreich ausgeführt werden kann.

Gibt es eine stabile Möglichkeit, Doctrine-Migrationen ohne solche offensichtlichen Probleme wie erwähnt zu verwenden? Wir haben .sql Dateien previosly verwendet, die eigentlich nicht viel besser sind, aber ich bin ziemlich sicher, dass es die richtige Art der Datenbankversionierung für ein Doctrine-benutzendes Projekt gibt?

Das Generieren von Migrationen basierend auf dem Unterschied zwischen Modellen und Schema ist großartig und ich möchte diese Möglichkeit weiterhin beibehalten.

Danke

Antwort

2

Ich Art, dies zu lösen, ist die Lösung nicht so schön, aber immer noch, ich denke, es wird anderen Menschen nützlich sein. Ich benutze CLI in der Tat habe ich bereits die Datei machen jedes Update machen die Nummer in der Datenbank, ähnlich der in der Timo-Antwort, bevor Sie diese Frage, aber das ist immer noch nicht sehr effektiv, aber es lohnt sich sowieso.

Was ich nächste Art von Lösungen Sachen getan habe, gehen Sie zu doctrine/lib/Doctrine/Migration/Builder.php Zeile 531. Es gibt die Definition der Standardklasse jede Migration wird erweitert. Da ich CLI benutze und keine Möglichkeit fand, Parameter an diesen Ort zu übergeben, habe ich gerade Doctrine_Migration_Base in eine andere Klasse MY_Doctrine_Migration_Base getauscht, die unten steht.

Wenn Sie nicht CLI verwenden, würde ich sagen, dass Sie versuchen sollten, Optionen zu übergeben und Quelle nicht zu ersetzen.

Also die unten genannte Klasse erweitert Doctrine_Migration_Base und überschreibt eine Reihe von Methoden zu denen, überprüft, ob es in Ordnung ist, Änderungen vorzunehmen und dann die übergeordnete Methode, um sie zu tun. Es deckt nicht alle Methoden ab, die ich gerade gemacht habe, als ich das geschrieben habe.

Jetzt erstellt jede Migration Doctrine erweitert meine Klasse, die die ursprünglich erwähnten Probleme verhindern soll.

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

Vorschläge, wie dies verbessert werden kann, sind willkommen.

0

Doctrine Migrationen können damit nicht umgehen. Leider haben wir alle diese Probleme, da die Migrationen in einer Transaktion nicht ausgeführt wurden.

Sie können dies verbessern, indem Sie ein Plugin hinzufügen. Siehe auch: Blog-Post

Die andere Möglichkeit besteht darin, vor der Migration eine Datenbanksicherung durchzuführen. Wenn etwas schief geht, können Sie die Sicherung erneut installieren. Sie können dies mit einem Shell-Skript automatisieren.

1

Wenn Sie den Doctrine-CLI verwenden, können Sie eine eigene Migrationsaufgabe schreiben, die die Datenbank vor der Migration sichert und die Sicherung wiederherstellt, wenn die Migration fehlschlägt. Ich habe etwas Ähnliches für unsere Symfonie/Doktrin Migrationen geschrieben.

Wenn Sie Ihre Taskklasse im richtigen Verzeichnis der Lehre cli setzen wird es in der Liste der verfügbaren Befehle angezeigt werden