Migraciones de Bases de Datos

Las migraciones son una manera conveniente para modificar su base de datos en una forma estructurada y organizada.

A menudo, en desarrollo, necesitamos actualizar los cambios en los entornos de producción. Algunos de estos cambios podrían ser modificaciones en la base de datos, como nuevos campos, nuevas tablas, eliminación de índices, etc.

Cuando se genera una migración se crea un conjunto de clases para describir cómo está estructurada la base de datos en ese preciso momento. Estas clases pueden utilizarse para sincronizar la estructura del esquema en bases de datos remotas configurando su base de datos para trabajar con los nuevos cambios que implementa la aplicación. Las migraciones describen estas transformaciones usando simple PHP.

Volcado de esquema

Las Herramientas de desarrollador de Phalcon proporcionan secuencias de comandos para administrar las migraciones (generación, ejecución y cancelación).

Las opciones disponibles para la generación de migraciones son:

Ejecutando este script sin ningún parámetro simplemente descargará todos los objetos (tablas y vistas) de la base de datos en clases de migración.

Cada migración tiene un identificador de versión asociado. El número de versión nos permite identificar si la migración es más reciente o no, de la actual 'versión' de nuestra base de datos. Las versiones también informarán a Phalcon del orden de ejecución, cuando se ejecuta una migración.

Cuando se genera una migración, las instrucciones se muestran en la consola para describir los diferentes pasos de la migración y el tiempo de ejecución de esas declaraciones. Al final, se genera la versión de la migración.

Por defecto la Herramienta para desarrolladores de Phalcon utiliza el directorio app/migrations para volcar los archivos de migración. Usted puede cambiar la ubicación ajustando uno de los parámetros en el script de generación. Cada tabla de la base de datos tiene su respectiva clase generada en un archivo separado en un directorio que referencia su versión:

Anatomía de la clase de migración

Cada archivo contiene una clase única que extiende la clase Phalcon\Mvc\Model\Migration. Estas clases normalmente tienen dos métodos: up() y down(). up() realiza la migración, mientras que down() la deshace.

up() también contiene los métodos magic y morphTable(). La magia viene cuando reconoce los cambios necesarios para sincronizar la tabla real en la base de datos a la descripción dada.

<?php

use Phalcon\Db\Column as Column;
use Phalcon\Db\Index as Index;
use Phalcon\Db\Reference as Reference;
use Phalcon\Mvc\Model\Migration;

class ProductsMigration_100 extends Migration
{
    public function up()
    {
        $this->morphTable(
            'products',
            [
                'columns' => [
                    new Column(
                        'id',
                        [
                            'type'          => Column::TYPE_INTEGER,
                            'size'          => 10,
                            'unsigned'      => true,
                            'notNull'       => true,
                            'autoIncrement' => true,
                            'first'         => true,
                        ]
                    ),
                    new Column(
                        'product_types_id',
                        [
                            'type'     => Column::TYPE_INTEGER,
                            'size'     => 10,
                            'unsigned' => true,
                            'notNull'  => true,
                            'after'    => 'id',
                        ]
                    ),
                    new Column(
                        'name',
                        [
                            'type'    => Column::TYPE_VARCHAR,
                            'size'    => 70,
                            'notNull' => true,
                            'after'   => 'product_types_id',
                        ]
                    ),
                    new Column(
                        'price',
                        [
                            'type'    => Column::TYPE_DECIMAL,
                            'size'    => 16,
                            'scale'   => 2,
                            'notNull' => true,
                            'after'   => 'name',
                        ]
                    ),
                ],
                'indexes' => [
                    new Index(
                        'PRIMARY',
                        [
                            'id',
                        ]
                    ),
                    new Index(
                        'product_types_id',
                        [
                            'product_types_id',
                        ]
                    ),
                ],
                'references' => [
                    new Reference(
                        'products_ibfk_1',
                        [
                            'referencedSchema'  => 'invo',
                            'referencedTable'   => 'product_types',
                            'columns'           => ['product_types_id'],
                            'referencedColumns' => ['id'],
                        ]
                    ),
                ],
                'options' => [
                    'TABLE_TYPE'      => 'BASE TABLE',
                    'ENGINE'          => 'InnoDB',
                    'TABLE_COLLATION' => 'utf8_general_ci',
                ],
            ]
        );
    }
}

La clase es llamada ProductsMigration_100. El sufijo 100 se refiere a la versión 1.0.0. morphTable() recibe un arreglo asociativo con 4 posibles secciones:

Índice Descripción Opcional
columns Una matriz con el conjunto de columnas de la tabla No
indexes Una matriz con el conjunto de índices de la tabla.
references Una matriz con el conjunto de referencias de la tabla (claves foráneas).
options Un array con un conjunto de opciones para crear la tabla. Estas opciones a menudo se relacionan con el sistema de base de datos en el que se generó la migración.

Definición de columnas

Phalcon\Db\Column se utiliza para definir las columnas de la tabla. Encapsula una gran variedad de características relacionadas con la columna. Su constructor recibe como primer parámetro el nombre de columna y como segundo, una matriz que describe la misma. Las siguientes opciones están disponibles cuando se describen las columnas:

Opción Descripción Opcional
type Tipo de columna. Debe ser una constante de Phalcon\Db\Column (ver lista de abajo) No
size Algunos tipos de columnas como VARCHAR o INTEGER puede tener un tamaño específico
scale Las columnas DECIMAL o NUMBER pueden tener una escala para especificar cuántos decimales deben almacenarse
unsigned Las columnas INTEGER puede tener o no signo. Esta opción no se aplica a otros tipos de columnas
notNull ¿La columna puede almacenar valores nulos?
default Define un valor predeterminado para una columna (sólo puede ser un valor real, no una función como NOW())
autoIncrement Con este atributo, la columna se completará automáticamente con un número entero auto-incremental. Solo una columna en la tabla puede tener este atributo.
primary Establece esta columna como clave primara, utilizando el índice columnName_pkey como identificador. Tipo BOOLEAN
first La columna debe colocarse en primera posición en el orden de columnas
after La columna debe colocarse después de la columna indicada

Las migraciones de bases de datos admiten los siguientes tipos de columna:

  • Phalcon\Db\Column::TYPE_INTEGER
  • Phalcon\Db\Column::TYPE_VARCHAR
  • Phalcon\Db\Column::TYPE_CHAR
  • Phalcon\Db\Column::TYPE_DATE
  • Phalcon\Db\Column::TYPE_DATETIME
  • Phalcon\Db\Column::TYPE_TIMESTAMP
  • Phalcon\Db\Column::TYPE_DECIMAL
  • Phalcon\Db\Column::TYPE_TEXT
  • Phalcon\Db\Column::TYPE_BOOLEAN
  • Phalcon\Db\Column::TYPE_FLOAT
  • Phalcon\Db\Column::TYPE_DOUBLE
  • Phalcon\Db\Column::TYPE_TINYBLOB
  • Phalcon\Db\Column::TYPE_BLOB
  • Phalcon\Db\Column::TYPE_MEDIUMBLOB
  • Phalcon\Db\Column::TYPE_LONGBLOB
  • Phalcon\Db\Column::TYPE_JSON
  • Phalcon\Db\Column::TYPE_JSONB
  • Phalcon\Db\Column::TYPE_BIGINTEGER

Definición de índices

Phalcon\Db\Index define los índices de la tabla. Un índice solo requiere que definas un nombre y una lista de sus columnas. Tenga en cuenta que si cualquier índice tiene el nombre PRIMARY, Phalcon creará un índice de clave principal para esa tabla.

Definición de referencias

Phalcon\Db\Reference define las referencias de la tabla (también llamadas llaves o claves foraneas). Las siguientes opciones pueden ser utilizadas para definir referencias:

Índice Descripción Opcional Implementado en
referencedTable Es auto descriptiva. Se refiere al nombre de la tabla a la que se hace referencia. No Todos
columns Una matriz con el nombre de las columnas en la tabla que tiene la referencia No Todos
referencedColumns Una matriz con el nombre de las columnas de la tabla de referencia No Todos
referencedSchema La tabla a la que se hace referencia puede estar en otro esquema o base de datos. Esta opción te permite definir eso. Todos
onDelete Si se elimina el registro foráneo, realizar esta acción en el o los registros locales. MySQL PostgreSQL
onUpdate Si se actualiza el registro foráneo, realizar esta acción en el o los registros locales. MySQL PostgreSQL

Escribiendo migraciones

Las migraciones no son sólo diseñadas para 'modificar' tablas. Una migración es sólo una clase regular de PHP por lo que no está limitado simplemente a estas funciones. Por ejemplo, después de agregar una columna, puedes escribir un código para establecer el valor de la columna en los registros existentes. Para más detalles y ejemplos de cada método, revise el componente de base de datos.

<?php

use Phalcon\Mvc\Model\Migration;

class ProductsMigration_100 extends Migration
{
    public function up()
    {
        // ...

        self::$_connection->insert(
            'products',
            [
                'Malabar spinach',
                14.50,
            ],
            [
                'name',
                'price',
            ]
        );
    }
}

Ejecutando migraciones

Una vez que las migraciones generadas se cargan en el servidor de destino, usted puede fácilmente ejecutarlas como se muestra en el ejemplo siguiente:

Dependiendo de cuan desactualizada este la base de datos con respecto a las migraciones, Phalcon puede ejecutar varias versiones de la migración en el mismo proceso de migración. Si especifica una versión de destino, Phalcon ejecutará las migraciones necesarias hasta llegar a la versión especificada.