Question

Nous utilisons les migrations de doctrine et il y a souvent des problèmes lors de la migration contient plusieurs actions et l'un d'entre eux tombe en panne.

Par exemple, s'il y a une migration en ajoutant 5 clés étrangères et le 5 d'entre eux échoue alors que champs ne sont pas de la même longueur, corriger l'erreur avec les champs et la régénération des migrations ne pas fix la chose, alors que maintenant il y a une erreur liée au fait 4 des clés existe déjà et ne permettent pas la migration de fonctionner avec succès.

Y at-il un moyen stable d'utiliser les migrations Doctrine sans ces problèmes évidents comme mentionné? Nous avons utilisé les fichiers .sql Antérieurement, qui ne sont pas beaucoup mieux en fait, mais je suis sûr qu'il ya droite mode de base de données versionning pour un projet en utilisant Doctrine?

migrations Génération en fonction de la différence entre les modèles et le schéma est grand et je voudrais garder cette possibilité en outre.

Merci

Était-ce utile?

La solution

Je sorte de résoudre cela, la solution est tout ce bien, mais encore, je suppose que ce sera utile à d'autres personnes. J'utilise CLI en effet, je l'ai déjà fait le fichier faisant chaque mise à jour de la migration du numéro dans la base de données, similaire à celle de la réponse du Timo avant de poser cette question, mais qui est toujours pas très efficace, mais la peine de faire de toute façon.

Qu'est-ce que je l'ai fait suivant genre de choses permet de résoudre, aller à doctrine/lib/Doctrine/Migration/Builder.php ligne 531. Il est la définition de la classe par défaut chaque migration volonté se prolonge. Depuis que je suis en utilisant CLI et ne pouvait pas trouver un moyen de passer des paramètres à cet endroit que je viens remplacé Doctrine_Migration_Base à un autre MY_Doctrine_Migration_Base de classe qui est au-dessous.

Si vous ne l'utilisez CLI je dirais que vous devriez essayer de passer des options et non remplacer la source.

Ainsi, la classe ci-dessous s'étend Doctrine_Migration_Base et effaceront tas de méthodes pour ceux, vérifier s'il est OK pour faire des changements, puis d'appeler la méthode parent pour les faire. Elle ne couvre pas toutes les méthodes actuellement, seulement ceux que j'ai rencontré quand j'ai écrit cela.

Maintenant, chaque migration Doctrine crée étend ma classe qui vise à prévenir les problèmes dont j'ai parlé à l'origine.

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

Des suggestions sur la façon d'améliorer ce sont les bienvenus.

Autres conseils

Si vous utilisez la doctrine-cli vous pouvez écrire votre propre tâche de migration qui sauvegarde la base de données avant la migration et restaure la sauvegarde si la migration échoue. J'ai écrit quelque chose de similaire pour nos migrations symfony / doctrine.

Si vous mettez votre classe de tâches dans le bon répertoire de la cli doctrine affichera dans la liste des commandes disponibles

migrations Doctrine ne peut pas gérer cela. Désolé de dire que nous avons tous ces problèmes, parce que les migrations ne sont pas exécutées dans une transaction.

Vous pouvez améliorer cela en ajoutant un plug-in. Voir: Blog-Post

L'autre possibilité est de faire une sauvegarde de base de données avant de migrer et si quelque chose va mal, vous pouvez réinstaller la sauvegarde. Vous pouvez automatiser cela par un script shell

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top