1. Base de datos
  2. Base de datos: Migraciones

Únete a nuestra comunidad de Telegram @webblend!

Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.

Introducción

Las migraciones son como control de versiones para su base de datos, permitiendo que su equipo defina y comparta la definición del esquema de la base de datos de la aplicación. Si alguna vez tuvo que decirle a un compañero de equipo que agregara manualmente una columna a su esquema de base de datos local después de extraer sus cambios del control de fuente, ha enfrentado el problema que resuelven las migraciones de bases de datos.

La fachada Schema de Laravel proporciona soporte independiente de la base de datos para crear y manipular tablas en todos los sistemas de bases de datos admitidos por Laravel. Por lo general, las migraciones usarán esta fachada para crear y modificar tablas y columnas de bases de datos.

Generación de Migraciones

Puede usar el comando Artisan make:migration para generar una migración de base de datos. La nueva migración se colocará en su directorio database/migrations. Cada nombre de archivo de migración contiene una marca de tiempo que permite a Laravel determinar el orden de las migraciones:

php artisan make:migration create_flights_table

Laravel utilizará el nombre de la migración para intentar adivinar el nombre de la tabla y si la migración creará o no una nueva tabla. Si Laravel puede determinar el nombre de la tabla a partir del nombre de la migración, Laravel completará automáticamente el archivo de migración generado con la tabla especificada. De lo contrario, puede especificar manualmente la tabla en el archivo de migración.

Si desea especificar una ruta personalizada para la migración generada, puede usar la opción --path al ejecutar el comando make:migration. La ruta dada debe ser relativa a la ruta base de su aplicación.

Nota Las plantillas de migración pueden personalizarse mediante publicación de plantillas.

Comprimiendo Migraciones

A medida que construye su aplicación, puede acumular más y más migraciones con el tiempo. Esto puede llevar a que su directorio database/migrations se llene de posiblemente cientos de migraciones. Si lo desea, puede "comprimir" sus migraciones en un solo archivo SQL. Para comenzar, ejecute el comando schema:dump:

php artisan schema:dump
 
# Dump the current database schema and prune all existing migrations...
php artisan schema:dump --prune

Cuando ejecute este comando, Laravel escribirá un archivo "esquema" en el directorio database/schema de su aplicación. El nombre del archivo de esquema corresponderá a la conexión de la base de datos. Ahora, cuando intente migrar su base de datos y no se hayan ejecutado otras migraciones, Laravel ejecutará primero las declaraciones SQL en el archivo de esquema de la conexión de la base de datos que está utilizando. Después de ejecutar las declaraciones SQL del archivo de esquema, Laravel ejecutará cualquier migración restante que no formara parte del volcado del esquema:

Si las pruebas de su aplicación utilizan una conexión de base de datos diferente a la que suele usar durante el desarrollo local, asegúrese de haber volcado un archivo de esquema usando esa conexión de base de datos para que sus pruebas puedan construir su base de datos. Puede desear hacer esto después de volcar la conexión de base de datos que suele usar durante el desarrollo local:

php artisan schema:dump
php artisan schema:dump --database=testing --prune

Debería comprometer su archivo de esquema de base de datos en el control de origen para que otros desarrolladores nuevos en su equipo puedan crear rápidamente la estructura inicial de la base de datos de su aplicación.

Advertencia La compresión de migraciones solo está disponible para las bases de datos MySQL, PostgreSQL y SQLite y utiliza el cliente de línea de comandos de la base de datos. Las volcadas de esquema no se pueden restaurar en bases de datos SQLite en memoria.

Estructura de Migración

Una clase de migración contiene dos métodos: up y down. El método up se utiliza para agregar nuevas tablas, columnas o índices a su base de datos, mientras que el método down debe revertir las operaciones realizadas por el método up.

Dentro de ambos de estos métodos, puede usar el generador de esquemas de Laravel para crear y modificar tablas de manera expresiva. Para conocer todos los métodos disponibles en el generador de esquemas Schema, consulte su documentación. Por ejemplo, la siguiente migración crea una tabla flights:

<?php
 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
return new class extends Migration
{
/**
* Ejecutar las migraciones.
*/
public function up(): void
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
 
/**
* Revertir las migraciones.
*/
public function down(): void
{
Schema::drop('flights');
}
};

Establecer la Conexión de Migración

Si su migración interactuará con una conexión de base de datos diferente a la conexión de base de datos predeterminada de su aplicación, debe establecer la propiedad $connection de su migración:

/**
* La conexión de base de datos que debería ser utilizada por la migración.
*
* @var string
*/
protected $connection = 'pgsql';
 
/**
* Ejecutar las migraciones.
*/
public function up(): void
{
// ...
}

Ejecución de Migraciones

Para ejecutar todas sus migraciones pendientes, ejecute el comando Artisan migrate:

php artisan migrate

Si desea ver qué migraciones se han ejecutado hasta ahora, puede usar el comando Artisan migrate:status:

php artisan migrate:status

Si desea ver las declaraciones SQL que se ejecutarán con las migraciones sin ejecutarlas realmente, puede proporcionar la bandera --pretend al comando migrate:

php artisan migrate --pretend

Aislamiento de la Ejecución de Migraciones

Si está implementando su aplicación en varios servidores y ejecutando migraciones como parte de su proceso de implementación, es probable que no desee que dos servidores intenten migrar la base de datos al mismo tiempo. Para evitar esto, puede usar la opción isolated al invocar el comando migrate.

Cuando se proporciona la opción isolated, Laravel adquirirá un bloqueo atómico utilizando el controlador de caché de su aplicación antes de intentar ejecutar sus migraciones. Todos los demás intentos de ejecutar el comando migrate mientras se mantiene ese bloqueo no se ejecutarán; sin embargo, el comando seguirá saliendo con un código de estado de salida exitoso:

php artisan migrate --isolated

Advertencia Para utilizar esta función, su aplicación debe utilizar los controladores de caché memcached, redis, dynamodb, database, file o array como controlador de caché predeterminado. Además, todos los servidores deben comunicarse con el mismo servidor central de caché.

Forzar la Ejecución de Migraciones en Producción

Algunas operaciones de migración son destructivas, lo que significa que pueden causar la pérdida de datos. Para protegerlo de ejecutar estos comandos contra su base de datos de producción, se le pedirá confirmación antes de que se ejecuten los comandos. Para forzar la ejecución de los comandos sin un aviso, use la bandera --force:

php artisan migrate --force

Reversión de Migraciones

Para deshacer la última operación de migración, puede usar el comando Artisan rollback. Este comando deshace el último "lote" de migraciones, que puede incluir varios archivos de migración:

php artisan migrate:rollback

Puede deshacer un número limitado de migraciones proporcionando la opción step al comando rollback. Por ejemplo, el siguiente comando deshará las últimas cinco migraciones:

php artisan migrate:rollback --step=5

Puede deshacer un "lote" específico de migraciones proporcionando la opción batch al comando rollback, donde la opción batch corresponde a un valor de lote dentro de la tabla de base de datos migrations de su aplicación. Por ejemplo, el siguiente comando deshará todas las migraciones en el lote tres:

php artisan migrate:rollback --batch=3

Si desea ver las declaraciones SQL que se ejecutarán con las migraciones sin ejecutarlas realmente, puede proporcionar la bandera --pretend al comando migrate:rollback:

php artisan migrate:rollback --pretend

El comando migrate:reset deshará todas las migraciones de su aplicación:

php artisan migrate:reset

Revertir y Migrar Usando un Solo Comando

El comando migrate:refresh deshará todas sus migraciones y luego ejecutará el comando migrate. Este comando recrea efectivamente toda su base de datos:

php artisan migrate:refresh
 
# Refresh the database and run all database seeds...
php artisan migrate:refresh --seed

Puede deshacer y volver a migrar un número limitado de migraciones proporcionando la opción step al comando refresh. Por ejemplo, el siguiente comando deshará y volverá a migrar las últimas cinco migraciones:

php artisan migrate:refresh --step=5

Eliminar Todas las Tablas y Migrar

El comando migrate:fresh eliminará todas las tablas de la base de datos y luego ejecutará el comando migrate:

php artisan migrate:fresh
 
php artisan migrate:fresh --seed

Advertencia El comando migrate:fresh eliminará todas las tablas de la base de datos independientemente de su prefijo. Este comando debe usarse con precaución al desarrollar en una base de datos compartida con otras aplicaciones.

Tablas

Creación de Tablas

Para crear una nueva tabla de base de datos, use el método create en la fachada Schema. El método create acepta dos argumentos: el primero es el nombre de la tabla, mientras que el segundo es un cierre que recibe un objeto Blueprint que se puede usar para definir la nueva tabla:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->timestamps();
});

Al crear la tabla, puede utilizar cualquiera de los métodos de columna del generador de esquemas para definir las columnas de la tabla.

Verificar la Existencia de Tablas / Columnas

Puede verificar la existencia de una tabla o columna utilizando los métodos hasTable y hasColumn:

if (Schema::hasTable('users')) {
// La tabla "users" existe...
}
 
if (Schema::hasColumn('users', 'email')) {
// La tabla "users" existe y tiene una columna "email"...
}

Opciones de Conexión y Tabla de la Base de Datos

Si desea realizar una operación de esquema en una conexión de base de datos que no sea la conexión predeterminada de su aplicación, utilice el método connection:

Schema::connection('sqlite')->create('users', function (Blueprint $table) {
$table->id();
});

Además, se pueden utilizar algunas otras propiedades y métodos para definir otros aspectos de la creación de la tabla. La propiedad engine se puede usar para especificar el motor de almacenamiento de la tabla al usar MySQL:

Schema::create('users', function (Blueprint $table) {
$table->engine = 'InnoDB';
 
// ...
});

Las propiedades charset y collation se pueden utilizar para especificar el conjunto de caracteres y la intercalación para la tabla creada al usar MySQL:

Schema::create('users', function (Blueprint $table) {
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
 
// ...
});

El método temporary se puede utilizar para indicar que la tabla debe ser "temporal". Las tablas temporales solo son visibles para la sesión de base de datos de la conexión actual y se eliminan automáticamente cuando se cierra la conexión:

Schema::create('calculations', function (Blueprint $table) {
$table->temporary();
 
// ...
});

Si desea agregar un "comentario" a una tabla de base de datos, puede invocar el método comment en la instancia de la tabla. Los comentarios de tabla solo son compatibles actualmente con MySQL y Postgres:

Schema::create('calculations', function (Blueprint $table) {
$table->comment('Business calculations');
 
// ...
});

Actualización de Tablas

El método table en la fachada Schema se puede utilizar para actualizar tablas existentes. Al igual que el método create, el método table acepta dos argumentos: el nombre de la tabla y un cierre que recibe una instancia de Blueprint que puede usar para agregar columnas o índices a la tabla:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});

Renombrar / Eliminar Tablas

Para cambiar el nombre de una tabla de base de datos existente, utilice el método rename:

use Illuminate\Support\Facades\Schema;
 
Schema::rename($from, $to);

Para eliminar una tabla existente, puede utilizar los métodos drop o dropIfExists:

Schema::drop('users');
 
Schema::dropIfExists('users');

Renombrar Tablas con Claves Foráneas

Antes de cambiar el nombre de una tabla, debe verificar que las restricciones de clave externa en la tabla tengan un nombre explícito en sus archivos de migración en lugar de dejar que Laravel asigne un nombre basado en convenciones. De lo contrario, el nombre de la restricción de clave externa hará referencia al antiguo nombre de la tabla.

Columnas

Creación de Columnas

El método table en la fachada Schema se puede utilizar para actualizar tablas existentes. Al igual que el método create, el método table acepta dos argumentos: el nombre de la tabla y un cierre que recibe una instancia de Illuminate\Database\Schema\Blueprint que puede usar para agregar columnas a la tabla:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('users', function (Blueprint $table) {
$table->integer('votes');
});

Tipos de Columnas Disponibles

El generador de esquemas ofrece una variedad de métodos que corresponden a los diferentes tipos de columnas que puede agregar a sus tablas de base de datos. Cada uno de los métodos disponibles se enumera en la tabla a continuación:

bigIncrements()

El método bigIncrements crea una columna equivalente a UNSIGNED BIGINT (clave principal y autoincremento):

$table->bigIncrements('id');

bigInteger()

El método bigInteger crea una columna equivalente a BIGINT:

$table->bigInteger('votes');

binary()

El método binary crea una columna equivalente a BLOB:

$table->binary('photo');

boolean()

El método boolean crea una columna equivalente a BOOLEAN:

$table->boolean('confirmed');

char()

El método char crea una columna equivalente a CHAR con una longitud dada:

$table->char('name', 100);

dateTimeTz()

El método dateTimeTz crea una columna equivalente a DATETIME (con zona horaria) con una precisión opcional (dígitos totales):

$table->dateTimeTz('created_at', $precision = 0);

dateTime()

El método dateTime crea una columna equivalente a DATETIME con una precisión opcional (dígitos totales):

$table->dateTime('created_at', $precision = 0);

date()

El método date crea una columna equivalente a DATE:

$table->date('created_at');

decimal()

El método decimal crea una columna equivalente a DECIMAL con la precisión (dígitos totales) y la escala (dígitos decimales) dadas:

$table->decimal('amount', $precision = 8, $scale = 2);

double()

El método double crea una columna equivalente a DOUBLE con la precisión (dígitos totales) y la escala (dígitos decimales) dadas:

$table->double('amount', 8, 2);

enum()

El método enum crea una columna equivalente a ENUM con los valores válidos dados:

$table->enum('difficulty', ['easy', 'hard']);

float()

El método float crea una columna equivalente a FLOAT con la precisión (dígitos totales) y la escala (dígitos decimales) dadas:

$table->float('amount', 8, 2);

foreignId()

El método foreignId crea una columna equivalente a UNSIGNED BIGINT:

$table->foreignId('user_id');

foreignIdFor()

El método foreignIdFor agrega una columna {column}_id equivalente para una clase de modelo dada. El tipo de columna será UNSIGNED BIGINT, CHAR(36) o CHAR(26) según el tipo de clave del modelo:

$table->foreignIdFor(User::class);

foreignUlid()

El método foreignUlid crea una columna equivalente a ULID:

$table->foreignUlid('user_id');

foreignUuid()

El método foreignUuid crea una columna equivalente a UUID:

$table->foreignUuid('user_id');

geometryCollection()

El método geometryCollection crea una columna equivalente a GEOMETRYCOLLECTION:

$table->geometryCollection('positions');

geometry()

El método geometry crea una columna equivalente a GEOMETRY:

$table->geometry('positions');

id()

El método id es un alias del método bigIncrements. Por defecto, el método creará una columna id; sin embargo, puede pasar un nombre de columna si desea asignar un nombre diferente a la columna:

$table->id();

increments()

El método increments crea una columna equivalente a UNSIGNED INTEGER (clave principal y autoincremento):

$table->increments('id');

integer()

El método integer crea una columna equivalente a INTEGER:

$table->integer('votes');

ipAddress()

El método ipAddress crea una columna equivalente a VARCHAR:

$table->ipAddress('visitor');

Cuando se utiliza Postgres, se creará una columna INET.

json()

El método json crea una columna equivalente a JSON:

$table->json('options');

jsonb()

El método jsonb crea una columna equivalente a JSONB:

$table->jsonb('options');

lineString()

El método lineString crea una columna equivalente a LINESTRING:

$table->lineString('positions');

longText()

El método longText crea una columna equivalente a LONGTEXT:

$table->longText('description');

macAddress()

El método macAddress crea una columna destinada a contener una dirección MAC. Algunos sistemas de base de datos, como PostgreSQL, tienen un tipo de columna dedicado para este tipo de datos. Otros sistemas de base de datos usarán una columna equivalente de tipo cadena:

$table->macAddress('device');

mediumIncrements()

El método mediumIncrements crea una columna equivalente a UNSIGNED MEDIUMINT (clave principal y autoincremento):

$table->mediumIncrements('id');

mediumInteger()

El método mediumInteger crea una columna equivalente a MEDIUMINT:

$table->mediumInteger('votes');

mediumText()

El método mediumText crea una columna equivalente a MEDIUMTEXT:

$table->mediumText('description');

morphs()

El método morphs es un método de conveniencia que agrega una columna {column}_id equivalente y una columna {column}_type equivalente de tipo VARCHAR. El tipo de columna para {column}_id será UNSIGNED BIGINT, CHAR(36) o CHAR(26) según el tipo de clave del modelo.

Este método está destinado a utilizarse al definir las columnas necesarias para una relación polimórfica de Eloquent. En el siguiente ejemplo, se crearían las columnas taggable_id y taggable_type:

$table->morphs('taggable');

multiLineString()

El método multiLineString crea una columna equivalente a MULTILINESTRING:

$table->multiLineString('positions');

multiPoint()

El método multiPoint crea una columna equivalente a MULTIPOINT:

$table->multiPoint('positions');

multiPolygon()

El método multiPolygon crea una columna equivalente a MULTIPOLYGON:

$table->multiPolygon('positions');

nullableTimestamps()

El método nullableTimestamps es un alias del método timestamps:

$table->nullableTimestamps(0);

nullableMorphs()

El método es similar al método morphs; sin embargo, las columnas que se crean serán "anulables":

$table->nullableMorphs('taggable');

nullableUlidMorphs()

El método es similar al método ulidMorphs; sin embargo, las columnas que se crean serán "anulables":

$table->nullableUlidMorphs('taggable');

nullableUuidMorphs()

El método es similar al método uuidMorphs; sin embargo, las columnas que se crean serán "anulables":

$table->nullableUuidMorphs('taggable');

point()

El método point crea una columna equivalente a POINT:

$table->point('position');

polygon()

El método polygon crea una columna equivalente a POLYGON:

$table->polygon('position');

rememberToken()

El método rememberToken crea una columna anulable equivalente a VARCHAR(100) destinada a almacenar el actual "recordar token" token de autenticación:

$table->rememberToken();

set()

El método set crea una columna equivalente a SET con la lista dada de valores válidos:

$table->set('flavors', ['strawberry', 'vanilla']);

smallIncrements()

El método smallIncrements crea una columna equivalente a UNSIGNED SMALLINT (clave principal y autoincremento):

$table->smallIncrements('id');

smallInteger()

El método smallInteger crea una columna equivalente a SMALLINT:

$table->smallInteger('votes');

softDeletesTz()

El método softDeletesTz agrega una columna deleted_at anulable equivalente a TIMESTAMP (con zona horaria) con una precisión opcional (dígitos totales). Esta columna está destinada a almacenar la marca de tiempo deleted_at necesaria para la funcionalidad de "soft delete" de Eloquent:

$table->softDeletesTz($column = 'deleted_at', $precision = 0);

softDeletes()

El método softDeletes agrega una columna deleted_at anulable equivalente a TIMESTAMP con una precisión opcional (dígitos totales). Esta columna está destinada a almacenar la marca de tiempo deleted_at necesaria para la funcionalidad de "soft delete" de Eloquent:

$table->softDeletes($column = 'deleted_at', $precision = 0);

string()

El método string crea una columna equivalente a VARCHAR con la longitud dada:

$table->string('name', 100);

text()

El método text crea una columna equivalente a TEXT:

$table->text('description');

timeTz()

El método timeTz crea una columna equivalente a TIME (con zona horaria) con una precisión opcional (dígitos totales):

$table->timeTz('sunrise', $precision = 0);

time()

El método time crea una columna equivalente a TIME con una precisión opcional (dígitos totales):

$table->time('sunrise', $precision = 0);

timestampTz()

El método timestampTz crea una columna equivalente a TIMESTAMP (con zona horaria) con una precisión opcional (dígitos totales):

$table->timestampTz('added_at', $precision = 0);

timestamp()

El método timestamp crea una columna equivalente a TIMESTAMP con una precisión opcional (dígitos totales):

$table->timestamp('added_at', $precision = 0);

timestampsTz()

El método timestampsTz crea columnas created_at y updated_at equivalentes a TIMESTAMP (con zona horaria) con una precisión opcional (dígitos totales):

$table->timestampsTz($precision = 0);

timestamps()

El método timestamps crea columnas created_at y updated_at equivalentes a TIMESTAMP con una precisión opcional (dígitos totales):

$table->timestamps($precision = 0);

tinyIncrements()

El método tinyIncrements crea una columna equivalente a UNSIGNED TINYINT (clave principal y autoincremento):

$table->tinyIncrements('id');

tinyInteger()

El método tinyInteger crea una columna equivalente a TINYINT:

$table->tinyInteger('votes');

tinyText()

El método tinyText crea una columna equivalente a TINYTEXT:

$table->tinyText('notes');

unsignedBigInteger()

El método unsignedBigInteger crea una columna equivalente a UNSIGNED BIGINT:

$table->unsignedBigInteger('votes');

unsignedDecimal()

El método unsignedDecimal crea una columna equivalente a UNSIGNED DECIMAL con una precisión opcional (dígitos totales) y escala (dígitos decimales):

$table->unsignedDecimal('amount', $precision = 8, $scale = 2);

unsignedInteger()

El método unsignedInteger crea una columna equivalente a UNSIGNED INTEGER:

$table->unsignedInteger('votes');

unsignedMediumInteger()

El método unsignedMediumInteger crea una columna equivalente a UNSIGNED MEDIUMINT:

$table->unsignedMediumInteger('votes');

unsignedSmallInteger()

El método unsignedSmallInteger crea una columna equivalente a UNSIGNED SMALLINT:

$table->unsignedSmallInteger('votes');

unsignedTinyInteger()

El método unsignedTinyInteger crea una columna equivalente a UNSIGNED TINYINT:

$table->unsignedTinyInteger('votes');

ulidMorphs()

El método ulidMorphs es un método de conveniencia que agrega una columna {column}_id equivalente a CHAR(26) y una columna {column}_type equivalente de tipo VARCHAR.

Este método está destinado a utilizarse al definir las columnas necesarias para una relación polimórfica de Eloquent que utiliza identificadores ULID. En el siguiente ejemplo, se crearían las columnas taggable_id y taggable_type:

$table->ulidMorphs('taggable');

uuidMorphs()

El método uuidMorphs es un método de conveniencia que agrega una columna {column}_id equivalente a CHAR(36) y una columna {column}_type equivalente de tipo VARCHAR.

Este método está destinado a utilizarse al definir las columnas necesarias para una relación polimórfica de Eloquent que utiliza identificadores UUID. En el siguiente ejemplo, se crearían las columnas taggable_id y taggable_type:

$table->uuidMorphs('taggable');

ulid()

El método ulid crea una columna equivalente a ULID:

$table->ulid('id');

uuid()

El método uuid crea una columna equivalente a UUID:

$table->uuid('id');

year()

El método year crea una columna equivalente a YEAR:

$table->year('birth_year');

Modificadores de Columnas

Además de los tipos de columna enumerados anteriormente, hay varios "modificadores" de columna que puede usar al agregar una columna a una tabla de base de datos. Por ejemplo, para hacer que la columna sea "anulable", puede usar el método nullable:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('users', function (Blueprint $table) {
$table->string('email')->nullable();
});

La siguiente tabla contiene todos los modificadores de columna disponibles. Esta lista no incluye modificadores de índice:

Modificador Descripción
->after('column') Coloca la columna "después" de otra columna (MySQL).
->autoIncrement() Establece columnas INTEGER como autoincrementables (clave principal).
->charset('utf8mb4') Especifica un conjunto de caracteres para la columna (MySQL).
->collation('utf8mb4_unicode_ci') Especifica una intercalación para la columna (MySQL/PostgreSQL/SQL Server).
->comment('mi comentario') Agrega un comentario a una columna (MySQL/PostgreSQL).
->default($value) Especifica un valor "predeterminado" para la columna.
->first() Coloca la columna "primera" en la tabla (MySQL).
->from($integer) Establece el valor de inicio de un campo de autoincremento (MySQL / PostgreSQL).
->invisible() Hace que la columna sea "invisible" para las consultas SELECT * (MySQL).
->nullable($value = true) Permite insertar valores NULL en la columna.
->storedAs($expression) Crea una columna generada almacenada (MySQL / PostgreSQL).
->unsigned() Establece columnas INTEGER como UNSIGNED (MySQL).
->useCurrent() Establece columnas TIMESTAMP para usar CURRENT_TIMESTAMP como valor predeterminado.
->useCurrentOnUpdate() Establece columnas TIMESTAMP para usar CURRENT_TIMESTAMP cuando se actualiza un registro (MySQL).
->virtualAs($expression) Crea una columna generada virtual (MySQL / PostgreSQL / SQLite).
->generatedAs($expression) Crea una columna de identidad con opciones de secuencia especificadas (PostgreSQL).
->always() Define la precedencia de los valores de secuencia sobre la entrada para una columna de identidad (PostgreSQL).
->isGeometry() Establece el tipo de columna espacial a geometry - el tipo predeterminado es geography (PostgreSQL).

Expresiones Predeterminadas

El modificador default acepta un valor o una instancia de Illuminate\Database\Query\Expression. El uso de una instancia de Expression evitará que Laravel envuelva el valor entre comillas y le permitirá utilizar funciones específicas de la base de datos. Una situación en la que esto es particularmente útil es cuando necesita asignar valores predeterminados a columnas JSON:

<?php
 
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Migrations\Migration;
 
return new class extends Migration
{
/**
* Ejecutar las migraciones.
*/
public function up(): void
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->json('movies')->default(new Expression('(JSON_ARRAY())'));
$table->timestamps();
});
}
};

Advertencia El soporte para expresiones predeterminadas depende de su controlador de base de datos, la versión de la base de datos y el tipo de campo. Consulte la documentación de su base de datos.

Orden de Columnas

Al utilizar la base de datos MySQL, el método after se puede utilizar para agregar columnas después de una columna existente en el esquema:

$table->after('password', function (Blueprint $table) {
$table->string('address_line1');
$table->string('address_line2');
$table->string('city');
});

Modificación de Columnas

El método change le permite modificar el tipo y los atributos de columnas existentes. Por ejemplo, es posible que desee aumentar el tamaño de una columna string. Para ver el método change en acción, aumentemos el tamaño de la columna name de 25 a 50. Para lograr esto, simplemente definimos el nuevo estado de la columna y luego llamamos al método change:

Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change();
});

Al modificar una columna, debe incluir explícitamente todos los modificadores que desee conservar en la definición de la columna; cualquier atributo faltante se eliminará. Por ejemplo, para conservar los atributos unsigned, default y comment, debe llamar a cada modificador explícitamente al cambiar la columna:

Schema::table('users', function (Blueprint $table) {
$table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();
});

Modificación de Columnas en SQLite

Si su aplicación utiliza una base de datos SQLite, debe instalar el paquete doctrine/dbal mediante el gestor de paquetes Composer antes de modificar una columna. La biblioteca Doctrine DBAL se utiliza para determinar el estado actual de la columna y para crear las consultas SQL necesarias para realizar los cambios solicitados en su columna:

composer require doctrine/dbal

Si planea modificar columnas creadas utilizando el método timestamp, también debe agregar la siguiente configuración al archivo de configuración config/database.php de su aplicación:

use Illuminate\Database\DBAL\TimestampType;
 
'dbal' => [
'types' => [
'timestamp' => TimestampType::class,
],
],

Advertencia Cuando se utiliza el paquete doctrine/dbal, los siguientes tipos de columna se pueden modificar: bigInteger, binary, boolean, char, date, dateTime, dateTimeTz, decimal, double, integer, json, longText, mediumText, smallInteger, string, text, time, tinyText, unsignedBigInteger, unsignedInteger, unsignedSmallInteger, ulid, y uuid.

Renombrar Columnas

Para cambiar el nombre de una columna, puede utilizar el método renameColumn proporcionado por el generador de esquemas:

Schema::table('users', function (Blueprint $table) {
$table->renameColumn('from', 'to');
});

Renombrar Columnas en Bases de Datos Heredadas

Si está ejecutando una instalación de base de datos anterior a una de las siguientes versiones, asegúrese de haber instalado la biblioteca doctrine/dbal mediante el gestor de paquetes Composer antes de cambiar el nombre de una columna:

  • MySQL < 8.0.3
  • MariaDB < 10.5.2
  • SQLite < 3.25.0

Eliminar Columnas

Para eliminar una columna, puede utilizar el método dropColumn en el generador de esquemas:

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

Puede eliminar varias columnas de una tabla pasando un array de nombres de columna al método dropColumn:

Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['votes', 'avatar', 'location']);
});

Eliminar Columnas en Bases de Datos Heredadas

Si está utilizando una versión de SQLite anterior a 3.35.0, debe instalar el paquete doctrine/dbal mediante el gestor de paquetes Composer antes de que se pueda utilizar el método dropColumn. No se admite la eliminación o modificación de varias columnas en una sola migración mientras se utiliza este paquete.

Alias de Comandos Disponibles

Laravel proporciona varios métodos convenientes relacionados con la eliminación de tipos comunes de columnas. Cada uno de estos métodos se describe en la siguiente tabla:

Comando Descripción
$table->dropMorphs('morphable'); Elimina las columnas morphable_id y morphable_type.
$table->dropRememberToken(); Elimina la columna remember_token.
$table->dropSoftDeletes(); Elimina la columna deleted_at.
$table->dropSoftDeletesTz(); Alias del método dropSoftDeletes().
$table->dropTimestamps(); Elimina las columnas created_at y updated_at.
$table->dropTimestampsTz(); Alias del método dropTimestamps().

Índices

Creación de Índices

El generador de esquemas de Laravel admite varios tipos de índices. El siguiente ejemplo crea una nueva columna email y especifica que sus valores deben ser únicos. Para crear el índice, podemos encadenar el método unique en la definición de la columna:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('users', function (Blueprint $table) {
$table->string('email')->unique();
});

Alternativamente, puede crear el índice después de definir la columna. Para hacerlo, debe llamar al método unique en el esquema del generador de esquemas. Este método acepta el nombre de la columna que debería recibir un índice único:

$table->unique('email');

Incluso puede pasar un array de columnas a un método de índice para crear un índice compuesto:

$table->index(['account_id', 'created_at']);

Al crear un índice, Laravel generará automáticamente un nombre de índice basado en el nombre de la tabla, los nombres de columna y el tipo de índice, pero puede pasar un segundo argumento al método para especificar el nombre del índice usted mismo:

$table->unique('email', 'unique_email');

Tipos de Índices Disponibles

La clase blueprint del generador de esquemas de Laravel proporciona métodos para crear cada tipo de índice admitido por Laravel. Cada método de índice disponible acepta un segundo argumento opcional para especificar el nombre del índice. Si se omite, el nombre se derivará de los nombres de la tabla y columna(s) utilizados para el índice, así como el tipo de índice. Cada uno de los métodos de índice disponibles se describe en la siguiente tabla:

Comando Descripción
$table->primary('id'); Añade una clave primaria.
$table->primary(['id', 'parent_id']); Añade claves compuestas.
$table->unique('email'); Añade un índice único.
$table->index('state'); Añade un índice.
$table->fullText('body'); Añade un índice de texto completo (MySQL/PostgreSQL).
$table->fullText('body')->language('english'); Añade un índice de texto completo del idioma especificado (PostgreSQL).
$table->spatialIndex('location'); Añade un índice espacial (excepto SQLite).

Longitudes de Índices y MySQL / MariaDB

Por defecto, Laravel utiliza el conjunto de caracteres utf8mb4. Si está ejecutando una versión de MySQL anterior a la versión 5.7.7 o MariaDB anterior a la versión 10.2.2, es posible que deba configurar manualmente la longitud predeterminada de cadena generada por las migraciones para que MySQL pueda crear índices para ellas. Puede configurar la longitud predeterminada de cadena llamando al método Schema::defaultStringLength dentro del método boot de su clase App\Providers\AppServiceProvider:

use Illuminate\Support\Facades\Schema;
 
/**
* Iniciar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Schema::defaultStringLength(191);
}

Alternativamente, puede habilitar la opción innodb_large_prefix para su base de datos. Consulte la documentación de su base de datos para obtener instrucciones sobre cómo habilitar correctamente esta opción.

Renombrar Índices

Para cambiar el nombre de un índice, puede utilizar el método renameIndex proporcionado por el esquema del generador de esquemas. Este método acepta el nombre actual del índice como su primer argumento y el nombre deseado como su segundo argumento:

$table->renameIndex('from', 'to')

Advertencia Si su aplicación utiliza una base de datos SQLite, debe instalar el paquete doctrine/dbal a través del administrador de paquetes Composer antes de que se pueda usar el método renameIndex.

Eliminar Índices

Para eliminar un índice, debe especificar el nombre del índice. Por defecto, Laravel asigna automáticamente un nombre de índice basado en el nombre de la tabla, el nombre de la columna indexada y el tipo de índice. Aquí hay algunos ejemplos:

Comando Descripción
$table->dropPrimary('users_id_primary'); Elimina una clave primaria de la tabla "users".
$table->dropUnique('users_email_unique'); Elimina un índice único de la tabla "users".
$table->dropIndex('geo_state_index'); Elimina un índice básico de la tabla "geo".
$table->dropFullText('posts_body_fulltext'); Elimina un índice de texto completo de la tabla "posts".
$table->dropSpatialIndex('geo_location_spatialindex'); Eliminar un índice espacial de la tabla "geo" (excepto SQLite).

Si pasa un array de columnas a un método que elimina índices, se generará el nombre de índice convencional basado en el nombre de la tabla, las columnas y el tipo de índice:

Schema::table('geo', function (Blueprint $table) {
$table->dropIndex(['state']); // Drops index 'geo_state_index'
});

Restricciones de Claves Foráneas

Laravel también brinda soporte para crear restricciones de clave externa que se utilizan para forzar la integridad referencial a nivel de base de datos. Por ejemplo, definamos una columna user_id en la tabla posts que haga referencia a la columna id en una tabla users:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
 
$table->foreign('user_id')->references('id')->on('users');
});

Dado que esta sintaxis es bastante extensa, Laravel proporciona métodos adicionales más concisos que utilizan convenciones para ofrecer una mejor experiencia de desarrollo. Al utilizar el método foreignId para crear su columna, el ejemplo anterior se puede reescribir de la siguiente manera:

Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});

El método foreignId crea una columna equivalente a UNSIGNED BIGINT, mientras que el método constrained utilizará convenciones para determinar la tabla y la columna a la que se hace referencia. Si el nombre de su tabla no coincide con las convenciones de Laravel, puede proporcionarlo manualmente al método constrained. Además, también se puede especificar el nombre que se asignará al índice generado:

Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained(
table: 'users', indexName: 'posts_user_id'
);
});

También puede especificar la acción deseada para las propiedades "on delete" y "on update" de la restricción:

$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');

También se proporciona una sintaxis alternativa y expresiva para estas acciones:

Método Descripción
$table->cascadeOnUpdate(); Las actualizaciones deben cascada.
$table->restrictOnUpdate(); Las actualizaciones deben restringirse.
$table->cascadeOnDelete(); Las eliminaciones deben cascada.
$table->restrictOnDelete(); Las eliminaciones deben restringirse.
$table->nullOnDelete(); Las eliminaciones deben establecer el valor de la clave externa a nulo.

Cualquier modificador de columna adicional debe llamarse antes del método constrained:

$table->foreignId('user_id')
->nullable()
->constrained();

Eliminar Claves Foráneas

Para eliminar una clave externa, puede utilizar el método dropForeign, pasando el nombre de la restricción de clave externa que se va a eliminar como argumento. Las restricciones de clave externa utilizan la misma convención de nombres que los índices. En otras palabras, el nombre de la restricción de clave externa se basa en el nombre de la tabla y las columnas en la restricción, seguido por un sufijo "_foreign":

$table->dropForeign('posts_user_id_foreign');

Alternativamente, puede pasar un array que contenga el nombre de la columna que tiene la clave externa al método dropForeign. El array se convertirá en un nombre de restricción de clave externa utilizando las convenciones de nombres de restricción de Laravel:

$table->dropForeign(['user_id']);

Alternar Restricciones de Claves Foráneas

Puede habilitar o deshabilitar restricciones de clave externa dentro de sus migraciones utilizando los siguientes métodos:

Schema::enableForeignKeyConstraints();
 
Schema::disableForeignKeyConstraints();
 
Schema::withoutForeignKeyConstraints(function () {
// Restricciones desactivadas dentro de este bloque...
});

Advertencia SQLite deshabilita las restricciones de clave externa de forma predeterminada. Cuando use SQLite, asegúrese de habilitar el soporte de claves externas en la configuración de su base de datos antes de intentar crearlas en sus migraciones. Además, SQLite solo admite claves externas al crear la tabla y no cuando se alteran las tablas.

Eventos

Por conveniencia, cada operación de migración emitirá un evento. Todos los siguientes eventos extienden la clase base Illuminate\Database\Events\MigrationEvent:

Clase Descripción
Illuminate\Database\Events\MigrationsStarted Se va a ejecutar un lote de migraciones.
Illuminate\Database\Events\MigrationsEnded Se ha completado la ejecución de un lote de migraciones.
Illuminate\Database\Events\MigrationStarted Se va a ejecutar una sola migración.
Illuminate\Database\Events\MigrationEnded Se ha completado la ejecución de una sola migración.
Illuminate\Database\Events\SchemaDumped Se ha completado un volcado del esquema de la base de datos.
Illuminate\Database\Events\SchemaLoaded Se ha cargado un volcado existente del esquema de la base de datos.