Base de datos: Migraciones
- Introducción
- Generando Migraciones
- Estructura de la Migración
- Ejecutando Migraciones
- Tablas
- Columnas
- Índices
- Eventos
Introducción
Las migraciones son como control de versiones para tu base de datos, lo que permite a tu equipo definir y compartir la definición del esquema de la base de datos de la aplicación. Si alguna vez has tenido que decirle a un compañero de equipo que añada manualmente una columna a su esquema de base de datos local después de incorporar tus cambios desde el control de versiones, has enfrentado el problema que las migraciones de base de datos resuelven.
La Schema
facade de Laravel proporciona soporte agnóstico a bases de datos para crear y manipular tablas en todos los sistemas de bases de datos admitidos por Laravel. Típicamente, las migraciones utilizarán esta fachada para crear y modificar tablas y columnas de base de datos.
Generando Migraciones
Puedes usar el comando Artisan make:migration
para generar una migración de base de datos. La nueva migración se colocará en tu 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 rellenará automáticamente el archivo de migración generado con la tabla especificada. De lo contrario, puedes especificar la tabla en el archivo de migración manualmente.
Si deseas especificar una ruta personalizada para la migración generada, puedes utilizar la opción --path
al ejecutar el comando make:migration
. La ruta dada debe ser relativa a la ruta base de tu aplicación.
[!NOTA] Los stubs de migración se pueden personalizar utilizando la publicación de stubs.
Aplanando Migraciones
A medida que construyes tu aplicación, es posible que acumules más y más migraciones con el tiempo. Esto puede llevar a que tu directorio database/migrations
se vuelva engorroso con potencialmente cientos de migraciones. Si lo deseas, puedes "compactar" tus migraciones en un solo archivo SQL. Para comenzar, ejecuta el comando schema:dump
:
php artisan schema:dump # Dump the current database schema and prune all existing migrations...php artisan schema:dump --prune
Cuando ejecutes este comando, Laravel escribirá un archivo "schema" en el directorio database/schema
de tu aplicación. El nombre del archivo de esquema corresponderá a la conexión de base de datos. Ahora, cuando intentes migrar tu base de datos y no se hayan ejecutado otras migraciones, Laravel primero ejecutará las sentencias SQL en el archivo de esquema de la conexión de base de datos que estás utilizando. Después de ejecutar las sentencias SQL del archivo de esquema, Laravel ejecutará cualquier migración restante que no formara parte del volcado del esquema.
Si las pruebas de tu aplicación utilizan una conexión de base de datos diferente a la que sueles usar durante el desarrollo local, debes asegurarte de haber volcado un archivo de esquema utilizando esa conexión de base de datos para que tus pruebas puedan construir tu base de datos. Es posible que desees hacer esto después de volcar la conexión de base de datos que sueles usar durante el desarrollo local:
php artisan schema:dumpphp artisan schema:dump --database=testing --prune
Debes comprometer el archivo del esquema de tu base de datos al control de versiones para que otros desarrolladores nuevos en tu equipo puedan crear rápidamente la estructura de base de datos inicial de tu aplicación.
[!WARNING] La compactación de migraciones solo está disponible para las bases de datos MariaDB, MySQL, PostgreSQL y SQLite y utiliza el cliente de línea de comandos de la base de datos.
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 tu base de datos, mientras que el método down
debe revertir las operaciones realizadas por el método up
.
Dentro de ambos métodos, puedes usar el constructor de esquema de Laravel para crear y modificar tablas de manera expresiva. Para aprender sobre todos los métodos disponibles en el constructor Schema
, consulta 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{ /** * Run the migrations. */ public function up(): void { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('airline'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::drop('flights'); }};
Configurando la Conexión de Migración
Si tu migración estará interactuando con una conexión a base de datos diferente de la conexión a base de datos predeterminada de tu aplicación, deberías establecer la propiedad $connection
de tu migración:
/** * The database connection that should be used by the migration. * * @var string */protected $connection = 'pgsql'; /** * Run the migrations. */public function up(): void{ // ...}
Ejecutando Migraciones
Para ejecutar todas tus migraciones pendientes, ejecuta el comando Artisan migrate
:
php artisan migrate
Si deseas ver qué migraciones se han ejecutado hasta ahora, puedes usar el comando Artisan migrate:status
:
php artisan migrate:status
Si deseas ver las declaraciones SQL que se ejecutarán mediante las migraciones sin ejecutarlas realmente, puedes proporcionar la bandera --pretend
al comando migrate
:
php artisan migrate --pretend
Aislar la Ejecución de Migraciones
Si estás desplegando tu aplicación en múltiples servidores y ejecutando migraciones como parte de tu proceso de despliegue, es probable que no quieras que dos servidores intenten migrar la base de datos al mismo tiempo. Para evitar esto, puedes 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 driver de caché de tu aplicación antes de intentar ejecutar tus migraciones. Todos los otros intentos de ejecutar el comando migrate
mientras se mantiene ese bloqueo no se ejecutarán; sin embargo, el comando todavía saldrá con un código de estado de salida exitoso:
php artisan migrate --isolated
[!WARNING] Para utilizar esta función, tu aplicación debe estar utilizando el driver de caché
memcached
,redis
,dynamodb
,database
,file
oarray
como el driver de caché predeterminado de tu aplicación. Además, todos los servidores deben estar comunicándose con el mismo servidor de caché central.
Forzar la Ejecución de Migraciones en Producción
Algunas operaciones de migración son destructivas, lo que significa que pueden hacer que pierdas datos. Para protegerte de ejecutar estos comandos en tu base de datos de producción, se te pedirá confirmación antes de que se ejecuten los comandos. Para forzar la ejecución de los comandos sin un aviso, usa el flag --force
:
php artisan migrate --force
Revirtiendo Migraciones
Para deshacer la última operación de migración, puedes 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
Puedes revertir un número limitado de migraciones proporcionando la opción step
al comando rollback
. Por ejemplo, el siguiente comando revertirá las últimas cinco migraciones:
php artisan migrate:rollback --step=5
Puedes revertir un "batch" 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 migrations
de la base de datos de tu aplicación. Por ejemplo, el siguiente comando revertirá todas las migraciones en el lote tres:
php artisan migrate:rollback --batch=3
Si deseas ver las declaraciones SQL que se ejecutarán mediante las migraciones sin realmente ejecutarlas, puedes proporcionar el flag --pretend
al comando migrate:rollback
:
php artisan migrate:rollback --pretend
El comando migrate:reset
revertirá todas las migraciones de tu aplicación:
php artisan migrate:reset
Revertir y migrar utilizando un solo comando
El comando migrate:refresh
revertirá todas tus migraciones y luego ejecutará el comando migrate
. Este comando efectivamente vuelve a crear toda tu base de datos:
php artisan migrate:refresh # Refresh the database and run all database seeds...php artisan migrate:refresh --seed
Puedes deshacer y reiniciar 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
Por defecto, el comando migrate:fresh
solo elimina tablas de la conexión de base de datos predeterminada. Sin embargo, puedes usar la opción --database
para especificar la conexión de base de datos que se debe migrar. El nombre de la conexión de base de datos debe corresponder a una conexión definida en el archivo de configuración database
de tu aplicación configuración:
php artisan migrate:fresh --database=admin
[!WARNING] El comando
migrate:fresh
eliminará todas las tablas de la base de datos sin importar su prefijo. Este comando debe usarse con precaución al desarrollar en una base de datos que se comparte con otras aplicaciones.
Tablas
Creando Tablas
Para crear una nueva tabla de base de datos, utiliza 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 una función anónima 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, puedes usar cualquiera de los métodos de columna del generador de esquemas para definir las columnas de la tabla.
Determinando la Existencia de una Tabla / Columna
Puedes determinar la existencia de una tabla, columna o índice utilizando los métodos hasTable
, hasColumn
y hasIndex
:
if (Schema::hasTable('users')) { // The "users" table exists...} if (Schema::hasColumn('users', 'email')) { // The "users" table exists and has an "email" column...} if (Schema::hasIndex('users', ['email'], 'unique')) { // The "users" table exists and has a unique index on the "email" column...}
Conexión a la base de datos y opciones de tabla
Si deseas realizar una operación de esquema en una conexión de base de datos que no sea la conexión predeterminada de tu aplicación, utiliza el método connection
:
Schema::connection('sqlite')->create('users', function (Blueprint $table) { $table->id();});
Además, se pueden usar algunas otras propiedades y métodos para definir otros aspectos de la creación de la tabla. La propiedad engine
se puede utilizar para especificar el motor de almacenamiento de la tabla al utilizar MariaDB o 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 MariaDB o 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 deseas añadir un "comentario" a una tabla de base de datos, puedes invocar el método comment
en la instancia de la tabla. Los comentarios de tabla son actualmente solo soportados por MariaDB, MySQL y PostgreSQL:
Schema::create('calculations', function (Blueprint $table) { $table->comment('Business calculations'); // ...});
Actualizando Tablas
El método table
en la fachada Schema
se puede usar para actualizar tablas existentes. Al igual que el método create
, el método table
acepta dos argumentos: el nombre de la tabla y una función anónima que recibe una instancia de Blueprint
que puedes usar para añadir columnas o índices a la tabla:
Renombrando / Eliminando Tablas
Para renombrar una tabla de base de datos existente, utiliza el método rename
:
use Illuminate\Support\Facades\Schema; Schema::rename($from, $to);
Para eliminar una tabla existente, puedes usar los métodos drop
o dropIfExists
:
Schema::drop('users'); Schema::dropIfExists('users');
Renombrando Tablas Con Claves Foráneas
Antes de renombrar una tabla, debes verificar que cualquier restricción de clave externa en la tabla tenga un nombre explícito en tus archivos de migración en lugar de dejar que Laravel asigne un nombre basado en convención. De lo contrario, el nombre de la restricción de clave externa se referirá al antiguo nombre de la tabla.
Columnas
Creando Columnas
El método table
en la fachada Schema
se puede usar para actualizar tablas existentes. Al igual que el método create
, el método table
acepta dos argumentos: el nombre de la tabla y una función anónima que recibe una instancia de Illuminate\Database\Schema\Blueprint
que puedes 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 esquema de la construcción de planos ofrece una variedad de métodos que corresponden a los diferentes tipos de columnas que puedes añadir a tus tablas de base de datos. Cada uno de los métodos disponibles se enumera en la tabla a continuación:
bigIncrements bigInteger binary boolean char dateTimeTz dateTime date decimal double enum float foreignId foreignIdFor foreignUlid foreignUuid geography geometry id increments integer ipAddress json jsonb longText macAddress mediumIncrements mediumInteger mediumText morphs nullableMorphs nullableTimestamps nullableUlidMorphs nullableUuidMorphs rememberToken set smallIncrements smallInteger softDeletesTz softDeletes string text timeTz time timestampTz timestamp timestampsTz timestamps tinyIncrements tinyInteger tinyText unsignedBigInteger unsignedInteger unsignedMediumInteger unsignedSmallInteger unsignedTinyInteger ulidMorphs uuidMorphs ulid uuid year
bigIncrements()
El método bigIncrements
crea una columna equivalente UNSIGNED BIGINT
(clave primaria) que se auto-incrementa:
$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');
Al utilizar MySQL, MariaDB o SQL Server, puedes pasar los argumentos length
y fixed
para crear una columna equivalente a VARBINARY
o BINARY
:
$table->binary('data', length: 16); // VARBINARY(16) $table->binary('data', length: 16, fixed: true); // BINARY(16)
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', length: 100);
dateTimeTz()
El método dateTimeTz
crea una columna equivalente a DATETIME
(con zona horaria) con una precisión opcional de segundos fraccionarios:
$table->dateTimeTz('created_at', precision: 0);
dateTime()
El método dateTime
crea una columna equivalente a DATETIME
con una precisión opcional de segundos fraccionarios:
$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 dada (dígitos totales) y la escala (dígitos decimales):
$table->decimal('amount', total: 8, places: 2);
double()
El método double
crea una columna equivalente a DOUBLE
:
$table->double('amount');
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 dada:
$table->float('amount', precision: 53);
foreignId()
El método foreignId
crea una columna equivalente a UNSIGNED BIGINT
:
$table->foreignId('user_id');
foreignIdFor()
El método foreignIdFor
añade una columna equivalente {column}_id
para una clase de modelo dada. El tipo de columna será UNSIGNED BIGINT
, CHAR(36)
o CHAR(26)
dependiendo del 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');
geography()
El método geography
crea una columna equivalente a GEOGRAPHY
con el tipo espacial dado y el SRID (Identificador del Sistema de Referencia Espacial) dado:
$table->geography('coordinates', subtype: 'point', srid: 4326);
[!NOTE] El soporte para tipos espaciales depende de tu driver de base de datos. Consulta la documentación de tu base de datos. Si tu aplicación está utilizando una base de datos PostgreSQL, debes instalar la extensión PostGIS antes de que se pueda usar el método
geography
.
geometry()
El método geometry
crea una columna equivalente a GEOMETRY
con el tipo espacial dado y el SRID (Identificador de Sistema de Referencia Espacial):
$table->geometry('positions', subtype: 'point', srid: 0);
[!NOTE] El soporte para tipos espaciales depende de tu driver de base de datos. Por favor, consulta la documentación de tu base de datos. Si tu aplicación está utilizando una base de datos PostgreSQL, debes instalar la extensión PostGIS antes de que se pueda utilizar el método
geometry
.
id()
El método id
es un alias del método bigIncrements
. Por defecto, el método creará una columna id
; sin embargo, puedes pasar un nombre de columna si deseas asignar un nombre diferente a la columna:
$table->id();
increments()
El método increments
crea una columna equivalente a INTEGER
UNSIGNED
auto-incremental como clave primaria:
$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');
Al utilizar PostgreSQL, 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');
longText()
El método longText
crea una columna equivalente a LONGTEXT
:
$table->longText('description');
Al utilizar MySQL o MariaDB, puedes aplicar un conjunto de caracteres binary
a la columna para crear una columna equivalente a LONGBLOB
:
$table->longText('data')->charset('binary'); // LONGBLOB
macAddress()
El método macAddress
crea una columna que está destinada a contener una dirección MAC. Algunos sistemas de bases de datos, como PostgreSQL, tienen un tipo de columna dedicado para este tipo de datos. Otros sistemas de bases de datos utilizarán una columna equivalente a string:
$table->macAddress('device');
mediumIncrements()
El método mediumIncrements
crea una columna equivalente UNSIGNED MEDIUMINT
auto-incremental como clave primaria:
$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');
Al utilizar MySQL o MariaDB, puedes aplicar un conjunto de caracteres binary
a la columna para crear una columna equivalente a MEDIUMBLOB
:
$table->mediumText('data')->charset('binary'); // MEDIUMBLOB
morphs()
El método morphs
es un método de conveniencia que añade una columna equivalente {column}_id
y una columna VARCHAR
equivalente {column}_type
. El tipo de columna para el {column}_id
será UNSIGNED BIGINT
, CHAR(36)
o CHAR(26)
, dependiendo del tipo de clave del modelo.
Este método está destinado a ser utilizado al definir las columnas necesarias para una relación Eloquent polimórfica. En el siguiente ejemplo, se crearían las columnas taggable_id
y taggable_type
:
$table->morphs('taggable');
nullableTimestamps()
El método nullableTimestamps
es un alias del método timestamps:
$table->nullableTimestamps(precision: 0);
nullableMorphs()
El método es similar al método morphs; sin embargo, las columnas que se crean serán "nullable":
$table->nullableMorphs('taggable');
nullableUlidMorphs()
El método es similar al método ulidMorphs; sin embargo, las columnas que se crearán serán "nullable":
$table->nullableUlidMorphs('taggable');
nullableUuidMorphs()
El método es similar al método uuidMorphs; sin embargo, las columnas que se crean serán "nullable":
$table->nullableUuidMorphs('taggable');
rememberToken()
El método rememberToken
crea una columna equivalente a VARCHAR(100)
que permite nulos y que está destinada a almacenar el token de autenticación "recuerdame" actual 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
de auto-incremento como clave primaria:
$table->smallIncrements('id');
smallInteger()
El método smallInteger
crea una columna equivalente a SMALLINT
:
$table->smallInteger('votes');
softDeletesTz()
El método softDeletesTz
añade una columna deleted_at
TIMESTAMP
(con zona horaria) equivalente y nullable, con una precisión de segundos fraccionarios opcional. Esta columna está destinada a almacenar la marca de tiempo deleted_at
necesaria para la funcionalidad de "eliminación suave" de Eloquent:
$table->softDeletesTz('deleted_at', precision: 0);
softDeletes()
El método softDeletes
añade una columna TIMESTAMP
equivalente deleted_at
que admite valores nulos, con una precisión de segundos fraccionarios opcional. Esta columna está destinada a almacenar la marca de tiempo deleted_at
necesaria para la funcionalidad de "eliminación suave" de Eloquent:
$table->softDeletes('deleted_at', precision: 0);
string()
El método string
crea una columna equivalente a VARCHAR
de la longitud dada:
$table->string('name', length: 100);
text()
El método text
crea una columna equivalente a TEXT
:
$table->text('description');
Al utilizar MySQL o MariaDB, puedes aplicar un conjunto de caracteres binary
a la columna para crear una columna equivalente a BLOB
:
$table->text('data')->charset('binary'); // BLOB
timeTz()
El método timeTz
crea una columna equivalente a TIME
(con zona horaria) con una precisión de segundos fraccionales opcional:
$table->timeTz('sunrise', precision: 0);
time()
El método time
crea una columna equivalente a TIME
con una precisión de segundos fraccionarios opcional:
$table->time('sunrise', precision: 0);
timestampTz()
El método timestampTz
crea una columna equivalente a TIMESTAMP
(con zona horaria) con una precisión de fracciones de segundo opcional:
$table->timestampTz('added_at', precision: 0);
timestamp()
El método timestamp
crea una columna equivalente a TIMESTAMP
con una precisión de segundos fraccionarios opcional:
$table->timestamp('added_at', precision: 0);
timestampsTz()
El método timestampsTz
crea columnas equivalentes created_at
y updated_at
TIMESTAMP
(con zona horaria) con una precisión de segundos fraccionarios opcional:
$table->timestampsTz(precision: 0);
timestamps()
El método timestamps
crea columnas TIMESTAMP
equivalentes created_at
y updated_at
con una precisión de segundos fraccionarios opcional:
$table->timestamps(precision: 0);
tinyIncrements()
El método tinyIncrements
crea una columna equivalente UNSIGNED TINYINT
de autoincremento como clave primaria:
$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');
Al utilizar MySQL o MariaDB, puedes aplicar un conjunto de caracteres binary
a la columna para crear una columna equivalente a TINYBLOB
:
$table->tinyText('data')->charset('binary'); // TINYBLOB
unsignedBigInteger()
El método unsignedBigInteger
crea una columna equivalente a UNSIGNED BIGINT
:
$table->unsignedBigInteger('votes');
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 añade una columna equivalente {column}_id
CHAR(26)
y una columna equivalente {column}_type
VARCHAR
.
Este método está destinado a ser utilizado al definir las columnas necesarias para una relación Eloquent polimórfica 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 añade una columna {column}_id
CHAR(36)
equivalente y una columna {column}_type
VARCHAR
equivalente.
Este método está destinado a utilizarse al definir las columnas necesarias para una relación Eloquent polimórfica 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 Columna
Además de los tipos de columna listados anteriormente, hay varios "modificadores" de columna que puedes usar al agregar una columna a una tabla de base de datos. Por ejemplo, para hacer que la columna sea "nullable", puedes 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 (MariaDB / MySQL). |
->autoIncrement() |
Establece columnas INTEGER como auto-incrementales (clave primaria). |
->charset('utf8mb4') |
Especifica un conjunto de caracteres para la columna (MariaDB / MySQL). |
->collation('utf8mb4_unicode_ci') |
Especifica una colación para la columna. |
->comment('my comment') |
Añade un comentario a una columna (MariaDB / MySQL / PostgreSQL). |
->default($value) |
Especifica un valor "por defecto" para la columna. |
->first() |
Coloca la columna "primera" en la tabla (MariaDB / MySQL). |
->from($integer) |
Establece el valor inicial de un campo auto-incrementable (MariaDB / MySQL / PostgreSQL). |
->invisible() |
Hace que la columna sea "invisible" para consultas SELECT * (MariaDB / MySQL). |
->nullable($value = true) |
Permite que se inserten valores NULL en la columna. |
->storedAs($expression) |
Crea una columna generada almacenada (MariaDB / MySQL / PostgreSQL / SQLite). |
->unsigned() |
Establece columnas INTEGER como UNSIGNED (MariaDB / MySQL). |
->useCurrent() |
Establece columnas TIMESTAMP para usar CURRENT_TIMESTAMP como valor por defecto. |
->useCurrentOnUpdate() |
Establece columnas TIMESTAMP para usar CURRENT_TIMESTAMP cuando se actualiza un registro (MariaDB / MySQL). |
->virtualAs($expression) |
Crea una columna generada virtual (MariaDB / MySQL / 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). |
Expresiones Predeterminadas
El modificador default
acepta un valor o una instancia de Illuminate\Database\Query\Expression
. Usar una instancia de Expression
evitará que Laravel envuelva el valor entre comillas y te permitirá usar funciones específicas de la base de datos. Una situación donde esto es especialmente útil es cuando necesitas 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{ /** * Run the migrations. */ public function up(): void { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->json('movies')->default(new Expression('(JSON_ARRAY())')); $table->timestamps(); }); }};
[!WARNING] El soporte para expresiones por defecto depende de tu driver de base de datos, versión de base de datos y el tipo de campo. Por favor, consulta la documentación de tu base de datos.
Orden de Columnas
Al utilizar la base de datos MariaDB o MySQL, el método after
puede usarse para añadir 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');});
Modificando Columnas
El método change
te permite modificar el tipo y los atributos de las columnas existentes. Por ejemplo, es posible que desees 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, debes incluir explícitamente todos los modificadores que deseas mantener en la definición de la columna; cualquier atributo que falte será eliminado. Por ejemplo, para retener los atributos unsigned
, default
y comment
, debes llamar a cada modificador de forma explícita al cambiar la columna:
Schema::table('users', function (Blueprint $table) { $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();});
El método change
no cambia los índices de la columna. Por lo tanto, puedes usar modificadores de índice para agregar o eliminar explícitamente un índice al modificar la columna:
// Add an index...$table->bigIncrements('id')->primary()->change(); // Drop an index...$table->char('postal_code', 10)->unique(false)->change();
Renombrando Columnas
Para renombrar una columna, puedes usar el método renameColumn
proporcionado por el constructor de esquemas:
Schema::table('users', function (Blueprint $table) { $table->renameColumn('from', 'to');});
Eliminando Columnas
Para eliminar una columna, puedes usar el método dropColumn
en el constructor de esquemas:
Schema::table('users', function (Blueprint $table) { $table->dropColumn('votes');});
Puedes eliminar múltiples 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']);});
Aliases de Comando Disponibles
Laravel ofrece varios métodos convenientes relacionados con la eliminación de tipos comunes de columnas. Cada uno de estos métodos se describe en la tabla a continuación:
Comando | Descripción |
---|---|
$table->dropMorphs('morphable'); |
Eliminar las columnas morphable_id y morphable_type . |
$table->dropRememberToken(); |
Eliminar la columna remember_token . |
$table->dropSoftDeletes(); |
Eliminar la columna deleted_at . |
$table->dropSoftDeletesTz(); |
Alias del método dropSoftDeletes() . |
$table->dropTimestamps(); |
Eliminar las columnas created_at y updated_at . |
$table->dropTimestampsTz(); |
Alias del método dropTimestamps() . |
Índices
Creando Índices
El constructor 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
a 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, puedes crear el índice después de definir la columna. Para hacerlo, debes llamar al método unique
en el plano del generador de esquemas. Este método acepta el nombre de la columna que debe recibir un índice único:
$table->unique('email');
Puedes incluso 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 la tabla, los nombres de las columnas y el tipo de índice, pero puedes pasar un segundo argumento al método para especificar el nombre del índice tú mismo:
$table->unique('email', 'unique_email');
Tipos de Índice Disponibles
La clase blueprint del constructor de esquemas de Laravel proporciona métodos para crear cada tipo de índice soportado por Laravel. Cada método de índice 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 la(s) columna(s) utilizadas para el índice, así como del tipo de índice. Cada uno de los métodos de índice disponibles se describe en la tabla a continuación:
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 (MariaDB / 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). |
Renombrando Índices
Para renombrar un índice, puedes usar el método renameIndex
proporcionado por el blueprint del constructor de esquema. 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')
Eliminando Índices
Para eliminar un índice, debes 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'); |
Eliminar una clave primaria de la tabla "users". |
$table->dropUnique('users_email_unique'); |
Eliminar un índice único de la tabla "users". |
$table->dropIndex('geo_state_index'); |
Eliminar un índice básico de la tabla "geo". |
$table->dropFullText('posts_body_fulltext'); |
Eliminar un índice de texto completo de la tabla "posts". |
$table->dropSpatialIndex('geo_location_spatialindex'); |
Eliminar un índice espacial de la tabla "geo" (excepto SQLite). |
Schema::table('geo', function (Blueprint $table) { $table->dropIndex(['state']); // Drops index 'geo_state_index'});
Restricciones de Clave Foránea
Laravel también proporciona soporte para la creación de restricciones de clave foránea, 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 verbosa, Laravel ofrece métodos adicionales y más concisos que utilizan convenciones para proporcionar una mejor experiencia al desarrollador. Al usar el método foreignId
para crear tu columna, el ejemplo anterior se puede reescribir así:
Schema::table('posts', function (Blueprint $table) { $table->foreignId('user_id')->constrained();});
El método foreignId
crea una columna equivalente de UNSIGNED BIGINT
, mientras que el método constrained
utilizará convenciones para determinar la tabla y la columna que se están referenciando. Si el nombre de tu tabla no coincide con las convenciones de Laravel, puedes proporcionarlo manualmente al método constrained
. Además, el nombre que se debe asignar al índice generado también se puede especificar:
Schema::table('posts', function (Blueprint $table) { $table->foreignId('user_id')->constrained( table: 'users', indexName: 'posts_user_id' );});
También puedes 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 ofrece una sintaxis alternativa y expresiva para estas acciones:
Método | Descripción |
---|---|
$table->cascadeOnUpdate(); |
Las actualizaciones deben ser en cascada. |
$table->restrictOnUpdate(); |
Las actualizaciones deben ser restringidas. |
$table->noActionOnUpdate(); |
Sin acción en las actualizaciones. |
$table->cascadeOnDelete(); |
Las eliminaciones deben ser en cascada. |
$table->restrictOnDelete(); |
Las eliminaciones deben ser restringidas. |
$table->nullOnDelete(); |
Las eliminaciones deben establecer el valor de la clave foránea en null. |
$table->foreignId('user_id') ->nullable() ->constrained();
Eliminando Claves Foráneas
Para eliminar una clave foránea, puedes usar el método dropForeign
, pasando el nombre de la restricción de clave foránea que se va a eliminar como argumento. Las restricciones de clave foránea utilizan la misma convención de nombres que los índices. En otras palabras, el nombre de la restricción de clave foránea se basa en el nombre de la tabla y las columnas en la restricción, seguido de un sufijo "_foreign":
$table->dropForeign('posts_user_id_foreign');
Alternativamente, puedes pasar un array que contenga el nombre de la columna que tiene la clave foránea al método dropForeign
. El array se convertirá en un nombre de restricción de clave foránea utilizando las convenciones de nomenclatura de restricciones de Laravel:
$table->dropForeign(['user_id']);
Alternando las restricciones de clave foránea
Puedes habilitar o deshabilitar las restricciones de claves foráneas dentro de tus migraciones utilizando los siguientes métodos:
Schema::enableForeignKeyConstraints(); Schema::disableForeignKeyConstraints(); Schema::withoutForeignKeyConstraints(function () { // Constraints disabled within this closure...});
[!WARNING] SQLite desactiva las restricciones de claves foráneas por defecto. Al usar SQLite, asegúrate de habilitar el soporte de claves foráneas en tu configuración de base de datos antes de intentar crearlas en tus migraciones.
Eventos
Para mayor comodidad, cada operación de migración despachará un evento. Todos los siguientes eventos extienden la clase base Illuminate\Database\Events\MigrationEvent
:
Clase | Descripción |
---|---|
Illuminate\Database\Events\MigrationsStarted |
Un lote de migraciones está a punto de ser ejecutado. |
Illuminate\Database\Events\MigrationsEnded |
Un lote de migraciones ha terminado de ejecutarse. |
Illuminate\Database\Events\MigrationStarted |
Una sola migración está a punto de ser ejecutada. |
Illuminate\Database\Events\MigrationEnded |
Una sola migración ha terminado de ejecutarse. |
Illuminate\Database\Events\NoPendingMigrations |
Un comando de migración no encontró migraciones pendientes. |
Illuminate\Database\Events\SchemaDumped |
Se ha completado un volcado de esquema de base de datos. |
Illuminate\Database\Events\SchemaLoaded |
Se ha cargado un volcado de esquema de base de datos existente. |