Pregunta

Estamos utilizando las migraciones doctrina y a menudo hay problemas cuando la migración contiene múltiples acciones y uno de ellos falla.

Por ejemplo, si hay una migración añadiendo 5 claves externas y el quinto de ellos falla mientras que los campos no son de la misma longitud, corregir el error con los campos y la regeneración de las migraciones hace no fix todo el asunto, mientras que ahora hay un error relacionado con el hecho de 4 de las teclas ya existe y no permiten la migración se ejecute correctamente.

¿Hay una manera estable a utilizar migraciones doctrina sin este tipo de problemas obvios como se ha mencionado? Hemos utilizado los archivos .sql Anteriormente:, que no son en realidad mucho mejor, pero estoy bastante seguro de que es el derecho forma de la base de datos de versiones para un proyecto de uso de Doctrina?

Generación de migraciones en base a la diferencia entre los modelos y el esquema es grande y me gustaría mantener esta posibilidad, además,.

Gracias

¿Fue útil?

Solución

Yo como que soluciona esto, la solución no es tan buena, pero aún así, supongo que será de utilidad para otras personas. Estoy usando la CLI de hecho ya he hecho el archivo haciendo cada actualización de la migración del número en la base de datos, similar a la de la respuesta del Timo antes de hacer esta pregunta, pero que aún no es muy eficaz, pero vale la pena hacer de todos modos.

Lo que he hecho siguiente tipo de cosas resuelve, vaya a doctrine/lib/Doctrine/Migration/Builder.php línea 531. No es la definición de la clase por defecto toda voluntad se extiende la migración. Desde que estoy usando CLI y no podía encontrar una manera de pasar parámetros a este lugar yo sólo he sustituido Doctrine_Migration_Base a otro MY_Doctrine_Migration_Base clase que está por debajo.

Si usted no está utilizando CLI yo diría que usted debe tratar de pasar opciones y no sustitutiva de la fuente.

Así que el siguiente clase extiende Doctrine_Migration_Base y sobrescribe un montón de métodos a los que, comprobar si está bien que hacer cambios y luego llamar al método de los padres, para hacerlas. No cubre actualmente todos los métodos, sólo las que me he encontrado cuando escribí esto.

Ahora, cada migración crea Doctrina extiende mi clase que está dirigido a la prevención de los problemas que he mencionado al principio.

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

Las sugerencias sobre cómo mejorar este son bienvenidos.

Otros consejos

Si está utilizando la doctrina-cli usted puede escribir su propia tarea de migración que realiza copias de la base de datos antes de la migración y restaura la copia de seguridad si falla la migración. Escribí algo similar para nuestros Symfony migraciones / doctrina.

Si usted pone su clase de tarea en el directorio correcto de la doctrina de la CLI mostrará en la lista de comandos disponibles

migraciones doctrina no puede manejar esto. Siento decir que todo lo que tenemos estos problemas, debido a que las migraciones no se ha ejecutado en una transacción.

Se puede mejorar esto mediante la adición de un plugin. Ver: Blog-Post

La otra posibilidad es hacer una copia de seguridad de base de datos antes de migrar y si algo va mal puede volver a instalar la copia de seguridad. Puede automatizar este por un script de shell

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top