Migraciones

1. Introducción

En proyectos reales, En el desarrollo de una aplicación, suele ocurrir que el esquema de base de datos cambia continuamente: se añaden campos, se refactorizan tablas, se crean relaciones, se aplican restricciones, etc. Hacer estos cambios a mano en phpMyAdmin (o en un SQL suelto) suele romper la trazabilidad, dificulta el trabajo en equipo y hace frágiles los despliegues entre entornos (local, preproducción, producción).

Es cierto que una vez desarrollada la aplicación, la base de datos sigue siendo un elemento crítico, pero menos frecuentes, presentando pocos cambios (es algo ideal…).

Laravel resuelve esto con migraciones: una forma versionada, repetible y automatizable de definir la estructura de la base de datos como código. En un equipo, todos comparten el mismo histórico de cambios, y el proyecto puede “levantar” la base de datos desde cero de forma consistente.

A su vez, laravel nos va a ofrecer la posibilidad de poblar de forma automatizada las tablas de la base de datos, constituyendo un entorno ideal para poder probar nuestra aplicación según la vamos desarrollando.

Estos datos serán datos fictícios o datos faker, y constituirán un entorno ideal para poder probar nuestra aplicación.


Objetivos

Qué veremos aquí


  • - Identificar qué problema resuelven las migraciones en un proyecto web profesional.
  • - Crear migraciones desde consola y localizar su archivo en el proyecto.
  • - Aplicar, deshacer y rehacer migraciones usando comandos de Artisan.
  • - Modelar columnas, índices y claves foráneas con el Schema Builder.
  • - Diseñar migraciones seguras (reversibles) y mantenibles en equipo.
  • - Detectar errores comunes en migraciones y aplicar buenas prácticas.

Migración

Es un fichero PHP (una clase) que permite crear/modificar/eliminar tablas en nuestra aplicación (podríamos decir que es el principal uso que le vamos a dar).

Además, permite mantener un versionado del esquema de la base de datos, lo que hace posible replicarlo exactamente en cualquier entorno (desarrollo, pruebas o producción, o cuando se clone el proyecto) simplemente ejecutando un comando.

Schema Builder

Schema Builder es la API de Laravel que permite definir tablas, columnas, índices y restricciones de forma expresiva, sin necesidad de escribir SQL manualmente.

Se utiliza dentro de las migraciones para estructurar la base de datos mediante métodos como create, table, string, integer, foreignId, etc.

Cuando hablamos aquí de API, estamos indicando un conjunto de métodos públicos disponibles en Schema y Blueprint, que podemos usar directamente. Son intuitivos y no necesitamos conocer su implementación. Es una librería de utilidades que tenemos disponibles:

## Ejemplos de métodos disponibles
use Illuminate\Support\Facades\Schema;

    Schema::create()
    Schema::table()
    $table->string()
    $table->integer()
    $table->foreignId()
    $table->timestamps()
    $table->unique()
Blueprint

Es el objeto que representa el diseño de una tabla durante la ejecución de una migración.

Su uso es implícito, ya que Laravel lo inyecta, cuando usamos los métodos dentro de Schema::create() o Schema::table(). Permite permite definir columnas, índices y claves foráneas utilizando una sintaxis fluida y orientada a objetos.

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('student', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->string('address');
            $table->timestamps();
        });
up() / down()
up() / down()
  • up(): Crea elementos: contiene las instrucciones para aplicar el cambio (crear tabla, añadir columnas, modificar estructura).
  • down(): Elimina: revierte los cambios realizados en up() (eliminar tabla, eliminar columnas, etc.).

Esto permite que los cambios en la base de datos sean reversibles y controlados.

  public function up(): void
    {
        Schema::create('student', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            });
    }
  public function down(): void
    {
        Schema::dropIfExists('student');
   }
migrate / rollback / refresh

migrate / rollback / refresh son operaciones habituales ejecutadas desde Artisan:

  • migrate: aplica las migraciones pendientes y crea las tablas definidas.
  • rollback: revierte el último lote de migraciones ejecutadas.
  • refresh: revierte todas las migraciones y las vuelve a ejecutar desde cero (muy útil en desarrollo).

Estas operaciones permiten gestionar la evolución del esquema de la base de datos de forma controlada.


Las migraciones

Las migraciones se guardan en: database/migrations

Laravel registra qué migraciones se han ejecutado en una tabla interna llamada migrations

Aunque es algo que no vamos a usar, es interesante saber que el proyecto guarda el histórico de cambios en Git y la base de datos guarda el “estado aplicado” en la tabla migrations. Podríamos deshacer los 3 ultimos cambios por ejemplo o el último o deshacer todo, como veremos a continuación


Acciones concretas

  1. Crear migración (nombra el cambio)
  2. Programar up() y down() (reversible)
  3. Ejecutar migrate (aplica en tu DB local)
  4. Subir cambios a Git
  5. En otro entorno (otro compañero / servidor), ejecutar migrate y obtener el mismo esquema

1.- Crear migraciones desde consola (Artisan)
    php artisan make:migration create_students_table

2.- Modificar una tabla existente

php artisan make:migration add_phone_to_students_table

3.-Crear migración y modelo a la vez (opcional, pero común) Aunque no hemos visto qué es un modelo, lo vamos a necesitar para interactuar con la base de datos desde nuestra aplicación Lo estudiamos en el tema de modelos

php artisan make:model Student -m

Convención de nombres :

  • create_x_table para crear
  • add_y_to_x_table para añadir
  • remove_y_from_x_table para eliminar
  • update_x_table o change_y_in_x_table para cambios complejos

Estructura de una migración

Una migración típica tiene esta forma:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('students');
    }
};

Puntos importantes :

  • Schema::create define una tabla desde cero
  • Blueprint $table define columnas, índices, etc.
  • down() revierte de forma segura con dropIfExists
  • up() Ejecuta la migración creando los elementos especificados (crear o modificar)

Ejecutar migraciones

Las principales acciones que vamos a realizar con las migraciones son las siguientes

Ejecutar todas las migraciones pendientes

php artisan migrate

Consultar el estado de las migraciones

1
php artisan migrate:status

Deshacer última acción (última migración ejecutado)

1
php artisan migrate:rollback

Deshacer las últimas N migraciones ejecutadas

1
php artisan migrate:rollback --step=3

Reiniciar el esquema completo (rollback total + migrate)

1
php artisan migrate:refresh

Borrar todas las tablas y volverlo a crear (muy usado en desarrollo) Esta acción la haremos con mucha frecuencia

1
php artisan migrate:fresh

Borrar todo y además ejecutar los seeders

1
php artisan migrate:fresh --seed
Criterio profesional :

  • fresh es ideal para desarrollo local cuando puedes perder datos
  • en producción casi siempre se usa migrate (nunca fresh)

4.6. Tipos de columnas más habituales (Laravel 12)

Identificadores y timestamps
  • id(): BIGINT autoincremental
  • timestamps(): created_at / updated_at
  • softDeletes(): deleted_at para borrado lógico
1
2
3
4
5
Schema::create('students', function (Blueprint $table) {
    $table->id();
    $table->timestamps();
    $table->softDeletes();
});
Strings, texto y números
  • string: VARCHAR(255) por defecto
  • text: TEXT
  • integer, bigInteger
  • decimal(8,2) para importes
  • boolean
1
2
3
4
5
6
7
Schema::table('students', function (Blueprint $table) {
    $table->string('name', 120);
    $table->text('notes')->nullable();
    $table->integer('age')->nullable();
    $table->decimal('tuition_fee', 8, 2)->default(0);
    $table->boolean('active')->default(true);
});
Fechas
  • date, time, dateTime
  • timestamp
1
2
3
4
Schema::table('students', function (Blueprint $table) {
    $table->date('birth_date')->nullable();
    $table->dateTime('last_login_at')->nullable();
});

Índices y restricciones: performance + integridad

El tema de índices es muy importante y lo tenemos que tener muy claro

Índices y únicos
  • index() acelera búsquedas
  • unique() evita duplicados
1
2
3
4
Schema::table('students', function (Blueprint $table) {
    $table->string('dni', 12)->unique();
    $table->string('city')->index();
});

Regla práctica :

  • index: para columnas que se filtran mucho (where)
  • unique: para “identificadores” (email, dni, código, etc.)

Resumen
  • Las migraciones nos van a permitir crear la base de datos y gestionarla
  • Permiten versionar el esquema de base de datos como código.
  • Se crean con make:migration y se aplican con migrate.
  • up() aplica cambios; down() los revierte: migraciones reversibles son más profesionales.
  • Schema Builder define columnas, índices y claves foráneas de forma expresiva.
  • Evita editar migraciones ya ejecutadas: crea nuevas migraciones para corregir/refactorizar.
  • En producción, normalmente se usa migrate (no fresh).

referencias


Seeders en Laravel

Inserción de datos iniciales o de prueba mediante Seeders en Laravel.