Migraciones de base de datos en laravel

Author
By Darío Rivera
Posted on 2019-07-08 in Laravel
Tags   Laravel 5.8

Las migraciones en laravel son lo más parecido a un sistema de control de versiones para una base de datos. Éstas permiten llevar un control sobre los cambios realizados al esquema de base de datos y brindan un mecanismo para la instalación de dichos cambios de manera automatizada. Cuántas veces hemos tenido que realizar un script de instalación para modificar o agregar algún campo en la base de datos en un sistema de producción ?. Cómo saber si dicho cambio ya fue instalado ? es posble realizar un rollback de dicho cambio ?. Laravel responde a éstas y muchas más preguntas a través de las migraciones. Veamos entonces sin más en que consisten.

Creación de migraciones

El comando general para crear una migración es el siguiente:

php artisan make:migration migration_name

En donde migration_name es el nombre de la migración que deseamos crear. Asi que para ver en qué consiste una migración vamos a ejecutar el siguiente comando en un proyecto configurado con laravel.

php artisan make:migration tabla_catalogo

La salida es este comando será similar a la siguiente:

Created migration: 2019_07_09_023027_tabla_catalogo

El nombre del archivo de migración es generado aleatoriamente por artisan y corresponde a la fecha actual concatenada con un tipo de timestamp y el argumento que hemos digitado en el comando make:migration. Esta nueva migración estará situada en el directorio database/migrations y tendrá el siguiente contenido:

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TablaCatalogo extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
}

Básicamente nuestra migración tiene dos métodos, up y down los cuáles sirven para agregar nuevas tablas, columnas, índices entre otros, y para reversar los cambios realizados respectivamente. Lo siguiente que vamos a ver ahora es cómo crear una tabla, su definición de campos, constraints y demás.

Definición de tablas

Para la definición de una tabla de base de datos resulta mucho más sencillo ejecutar el siguiente comando que crea un scaffolding para la estructura de la tabla:

php artisan make:migration create_catalogo_table

Lo primero que hay que denotar aquí (antes de revisar la migración) es que el anterior comando hace referencia a un patrón definido por create_mitabla_table el cuál siempre creará la tabla con el nombre encerrado por los caracteres _ (underscore). Para nuestro caso particular creará un archivo de migración para la tabla catalogo.

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCatalogoTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('catalogo', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('catalogo');
    }
}

En segundo lugar, podemos observar que laravel automáticamente ha creado el reverso de la migración por lo cuál no tendremos que preocuparnos por ello. Tanto el método up como down utilizan el facade Schema el cual provee un gran número de utilidades para la definición del esquema de la base de datos y validaciones. Por ahora es menester ver cómo podemos crear los distintos tipos de datos (o al menos los más utilizados) en bases de datos. Veamos a continuación la definición de nuestra tabla catalogo con varios tipos de datos.

Schema::create('catalogo', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('description');
    $table->string('marca')->nullable();
    $table->string('modelo', 30)->nullable();
    $table->text('observaciones');
    $table->date('proxima_revision');
    $table->integer('stock_minimo');
    $table->decimal('valor_unitario', 8, 2);
    $table->enum('estado', ['activo', 'inactivo']);
    $table->timestamps();
});

Por simplicidad hemos colocado solamente el contenido del método up. Analicemos pues cada línea de la anterior definición tomando como base que se ha ejecutado en el motor de base de datos Mysql.

$table->bigIncrements('id');

El método bigIncrements crea un campo bigint de longitud 20, unsigned y que es la llave primaria de la tabla.

$table->string('description');

El método string crea un campo de tipo varchar de longitud 255.

$table->string('marca')->nullable();

En este caso, la única diferencia con la anterior definición es que la columna se creará con posibilidad de insertar valores nulos en ella.

$table->string('modelo', 30)->nullable();

Si se agrega un segundo parámetro al método string definirá también la longitud del campo.

$table->text('observaciones');

El método text crea una columna de tipo text en la tabla.

$table->date('proxima_revision');

El método date crea una columna de tipo  date en la tabla.

$table->$table->integer('stock_minimo');

El método integer crear una columna de tipo int de longitud 11 en la tabla.

$table->decimal('valor_unitario', 8, 2);

El método decimal crea una columna de tipo decimal con precisión 8 y escala 2.

$table->enum('estado', ['activo', 'inactivo']);

El método enum crear una columna de tipo enum con los valores permitidos pasados como segundo parámetro en el array.

Modificación de tablas

Para modificar una definición de tabla se debe utilizar como último método de la sentencia de definición de un campo el método change de la siguiente forma:

Schema::table('catalogo', function (Blueprint $table) {
    $table->string('description', 50)->nullable()->change();
});

Este tipo de modificaciones suele utilizarse en sistema de producción en donde ya está instalada una versión funcional del software, además de hacerlo en una migración particular independiente a la de creación de la tabla. De lo contrario, en entornos de desarrollo suena mucho más lógico realizar dicha modificación sobre la migración de creación de la tabla.

Para eliminar una columna basta utilizar el método drop.

Schema::table('catalogo', function (Blueprint $table) {
    $table->dropColumn('marca');
});

Código SQL en migraciones

Si la alteración que se va a realizar a la base de datos es demasiado particular entonces y definitivamente no encuentras una manera de realizarlo de forma nativa en laravel entonces puedes utilizar el facade DB.

DB::statement("UPDATE credit_concepts SET description = SUBSTR(description, 1, 60)");

Ejecución de migraciones

La manera de ejecutar las migraciones pendientes es mediante el comando:

php artisan migrate

Laravel realizará la ejecución de las migraciones que no se hayan ejecutado, de esta manera se asegura que en entornos de producción no se vuelvan a correr los comandos para crear las tablas que ya tenemos. Si ejecutas este comando en un proyecto limpio de laravel podrá ver una salida similar a la siguiente:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table
Migrating: 2019_07_09_025421_create_catalogo_table
Migrated:  2019_07_09_025421_create_catalogo_table

Laravel contiene por defecto dos migraciones para crear una tabla de usuarios (users) y recuperación de contraseñas (create_password_resets_table). Si no lo consideras necesario puedes eliminar estas migraciones. Para consultar más a profundidad este tema de las migraciones te recomiendo consultar la documentación oficial en el siguiente link:

https://laravel.com/docs/5.8/migrations

Espero que este post te haya servido y que te haya dado las herramientas necesarias para seguir con temas más avanzados. Hasta la próxima!.


Si te ha gustado este artículo puedes invitarme a tomar una taza de café

Acerca de Darío Rivera

Author

Ingeniero de desarrollo en PlacetoPay , Medellín. Darío ha trabajado por más de 6 años en lenguajes de programación web especialmente en PHP. Creador del microframework DronePHP basado en Zend y Laravel.

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.