Las migraciones y los sembradores son poderosas utilidades de bases de datos que se proporcionan a través del marco PHP Laravel para permitir a los desarrolladores iniciar, destruir y volver a crear rápidamente la base de datos de una aplicación. Estas utilidades permiten minimizar los problemas de inconsistencia que pueden surgir en la base de datos cuando varios desarrolladores trabajan en la misma aplicación: los nuevos colaboradores solo deben ejecutar un par de comandos artisan para configurar la base de datos
en una nueva instalación.
A lo largo de esta guía, crearemos migraciones y alimentadores para completar una base de datos de aplicación de demostración de Laravel con datos de ejemplo. Al final, podrá destruir y volver a crear las tablas de su base de datos cuantas veces lo desee, usando solo comandos artisan
.
Para completar los pasos de esta guía, necesitará lo siguiente:
Nota: En esta guía, para ejecutar la aplicación usaremos un entorno de desarrollo en contenedor administrado por Docker Compose, pero también puede optar por ejecutar la aplicación en un servidor LEMP. Para configurarlo, puede seguir nuestra guía Cómo instalar y configurar Laravel con LEMP en Ubuntu 18.04.
Para comenzar, obtendremos la aplicación Laravel de demostración de su repositorio de GitHub. Nos interesa la ramificación tutorial-02, en la que se incluye una configuración de Docker Compose
para ejecutar la aplicación en contenedores. En este ejemplo, descargaremos la aplicación en nuestra carpeta de inicio, pero puede usar cualquier directorio que elija:
- cd ~
- curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip
Debido a que descargamos el código de la aplicación como un archivo .zip
, necesitaremos el comando unzip
para desempaquetarlo. Si no lo hizo recientemente, actualice el índice local de paquetes de su computadora:
- sudo apt update
A continuación instale el paquete unzip
:
- sudo apt install unzip
Después de eso, descomprima el contenido de la aplicación:
- unzip travellist.zip
Luego para facilitar el acceso cambie el nombre del directorio desempaquetado por travellist-demo:
- mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo
En el siguiente paso, crearemos un archivo de configuración .env
para configurar la aplicación.
.env
de la aplicaciónEn Laravel, se utiliza un archivo .env
para establecer configuraciones dependientes del entorno, como las credenciales y cualquier información que pueda variar entre las implementaciones. Este archivo no está incluido en el control de revisiones.
Advertencia: En el archivo de configuración del entorno se encuentra información confidencial sobre su servidor, incluidas las credenciales de bases de datos y las claves de seguridad. Por ese motivo, nunca debe compartir públicamente este archivo.
Los valores incluidos en el archivo .env
tendrán prioridad sobre los valores establecidos en los archivos de configuración normales que se encuentran en el directorio config
. Para cada instalación en un nuevo entorno se requiere un archivo de entorno personalizado a fin de definir elementos como las configuraciones de conexión de bases de datos, las opciones de depuración y las URL de aplicación, entre otros elementos que pueden variar dependiendo del entorno en el que se ejecute la aplicación.
Diríjase al directorio travellist-demo
:
- cd travellist-demo
Ahora, crearemos un nuevo archivo .env
para personalizar las opciones de configuración para el entorno de desarrollo que configuraremos. En Laravel se incluye un archivo .env
de ejemplo que podemos copiar para crear el nuestro:
- cp .env.example .env
Abra este archivo utilzando nano
o el editor de texto que prefiera:
- nano .env
Así es como se ve su archivo .env
ahora:
APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password
…
En el archivo .env
actual de la aplicación de demostración travellist
se incluyen las configuraciones para usar el entorno en contenedor que creamos con Docker Compose en la última parte de esta serie. No necesita cambiar ninguno de estos valores, pero puede modificar DB_DATABASE
, DB_USERNAME
y DB_PASSWORD
si lo desea, ya que nuestro archivo docker-compose.yml
los obtiene automáticamente para configurar la base de datos de desarrollo. Solo asegúrese de que la variable DB_HOST
permanezca sin cambios, ya que esta hace referencia al nombre de nuestro servicio de base de datos dentro del entorno de Docker Compose.
Si realiza algún cambio en el archivo, asegúrese de guardarlo y cerrarlo presionando CTRL + X
, Y
y luego INTRO
.
Nota: Si optó por ejecutar la aplicación en un servidor LEMP, deberá cambiar los valores resaltados para reflejar la configuración de su propia base de datos, incluida la variable DB_HOST
.
Ahora usaremos Composer, la herramienta de administración de dependencias de PHP, para instalar las dependencias de la aplicación y garantizar que podamos ejecutar comandos artisan
.
Abra su entorno de Docker Compose con el comando siguiente. Con esto, se creará la imagen travellist
para el servicio app
y se extraerán las imágenes adicionales de Docker requeridas por los servicios de nginx
y db
a fin de crear el entorno de la aplicación:
- docker-compose up -d
OutputCreating network "travellist-demo_travellist" with driver "bridge"
Building app
Step 1/11 : FROM php:7.4-fpm
---> fa37bd6db22a
Step 2/11 : ARG user
---> Running in 9259bb2ac034
…
Creating travellist-app ... done
Creating travellist-nginx ... done
Creating travellist-db ... done
Esta operación puede tardar unos minutos en completarse. Una vez terminado el proceso, podemos ejecutar Composer para instalar las dependencias de la aplicación.
Para ejecutar composer
y otros comandos en el contenedor de servicio app
, usaremos docker-compose exec
. El comando exec
nos permite ejecutar cualquier comando que elijamos en los contenedores gestionados por Docker Compose. Se utiliza la siguiente sintaxis: docker-compose exec service_name command
.
Nota: En caso de optar por utilizar un servidor LEMP para ejecutar la aplicación de demostración, debe ignorar la parte de docker-compose exec
app de los comandos enumerados a lo largo de esta guía. Por ejemplo, en lugar de ejecutar el siguiente comando como está escrito, simplemente ejecutaría lo siguiente:
- composer install
Para ejecutar composer install
en el contenedor app
, ejecute lo siguiente:
- docker-compose exec app composer install
OutputLoading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 85 installs, 0 updates, 0 removals
- Installing doctrine/inflector (1.3.1): Downloading (100%)
- Installing doctrine/lexer (1.2.0): Downloading (100%)
- Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)
…
Cuando Composer termine de instalar las dependencias de la aplicación, podrá ejecutar los comandos artisan
. Para verificar que en la aplicación se pueda establecer conexión con la base de datos, ejecute el siguiente comando en el que se eliminará cualquier tabla existente:
- docker-compose exec app php artisan db:wipe
Con este comando se eliminará cualquier tabla ya existente de la base de datos configurada. Si se ejecutó con éxito y en la aplicación se pudo establecer conexión con la base de datos, verá un resultado como el siguiente:
OutputDropped all tables successfully.
Ahora que instaló las dependencias de la aplicación con Composer, puede usar la herramienta artisan
para crear migraciones y alimentadores.
En la herramienta de línea de comandos artisan
que se incluye con Laravel hay una serie de comandos auxiliares que pueden utilizarse para administrar la aplicación e iniciar nuevas clases. Para generar una nueva clase de migración, podemos usar el comando make:migration
de la siguiente manera:
- docker-compose exec app php artisan make:migration create_places_table
Laravel infiere la operación que se ejecutará (create
), el nombre de la tabla (places
) y si en esta migración se creará una tabla nueva o no, basada en el nombre descriptivo proporcionado al comando make:migration
.
Verá un resultado similar a este:
OutputCreated Migration: 2020_02_03_143622_create_places_table
Con esto se generará un nuevo archivo en el directorio database/migrations
de la aplicación. Laravel utiliza la marca de tiempo incluida en el archivo generado automáticamente para determinar el orden en que se deben ejecutar las migraciones.
Utilice su editor de texto preferido para abrir el archivo de migración generado. Recuerde sustituir el valor resaltado por el nombre de su propio archivo de migración:
- nano database/migrations/2020_02_03_143622_create_places_table.php
En el archivo de migración generado se incluye una clase llamada CreatePlacesTable
:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePlacesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('places', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('places');
}
}
En esta clase se incluyen dos métodos: up
y down
. Ambos métodos contienen código de arranque que puede ampliar para personalizar lo que ocurre cuando se ejecuta esa migración y también lo que sucede cuando se revierte.
Modificaremos el método up
para que en la tabla places
se refleje la estructura que ya estamos usando en la versión actual de la aplicación:
id
: campo de clave primaria.name
: nombre del lugar.visited
: indica si este lugar ya recibió visitas o no.En el constructor de esquemas de Laravel se exponen los métodos para crear, actualizar y eliminar tablas de una base de datos. En la clase Blueprint
se define la estructura de la tabla y se proporcionan varios métodos para abstraer la definición de cada campo de la tabla.
En el código generado automáticamente se establece un campo de id
primario llamado id. En el método timestamps
se crean dos campos datetime
que las clases de base de datos subyacentes actualizan de manera automática cuando se insertan o actualizan datos dentro de la tabla. Además de estas, tendremos que incluir un campo name
y otro visited
.
Nuestro campo name
será del tipo string
y nuestro campo visited
estará configurado con el tipo boolean
. También estableceremos un valor predeterminado 0
para el campo visited, de modo que si no se transmite ningún valor, significa que aún no se visitó
el lugar. El método up
tendrá ahora el siguiente aspecto:
…
public function up()
{
Schema::create('places', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 100);
$table->boolean('visited')->default(0);
$table->timestamps();
});
}
…
Nota: Puede encontrar la lista completa de tipos de columnas disponibles en la documentación de Laravel.
Después de incluir las dos líneas resaltadas en su propia secuencia de comandos de migración, guarde y cierre el archivo.
Su migración estará lista para ejecutarse a través de artisan migrate
. Sin embargo, eso solo crearía una tabla vacía; también debemos poder insertar datos de ejemplo para desarrollo y pruebas. En el siguiente paso, veremos cómo hacerlo usando alimentadores de bases de datos.
Un alimentador es una clase especial que se utiliza para generar e insertar datos de ejemplo (semillas) en una base de datos. Esta es una característica importante en los entornos de desarrollo, ya que le permite volver a crear la aplicación con una base de datos nueva usando valores de ejemplo que de otra manera tendría que insertar manualmente al volver a crear la base de datos.
Ahora, usaremos el comando artisan
a fin de generar una nueva clase de alimentador para nuestra tabla places
llamada PlacesTableSeeder
:
- docker-compose exec app php artisan make:seeder PlacesTableSeeder
Con el comando se creará un nuevo archivo llamado PlacesTableSeeder.php
dentro del directorio database/seeds
. Abra el archivo usando su editor de texto preferido:
- nano database/seeds/PlacesTableSeeder.php
El archivo PlacesTableSeeder.php
generado automáticamente tiene el siguiente aspecto:
<?php
use Illuminate\Database\Seeder;
class PlacesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
}
}
Nuestra nueva clase de alimentador contiene un método vacío llamado run
. Este método se invocará cuando se ejecute el comando db:seed
de Artisan.
Debemos editar el método run
para que se incluyan las instrucciones de inserción de datos de ejemplo en la base de datos. Usaremos el generador de consultas de Laravel para simplificar este proceso.
El generador de consultas de Laravel ofrece una interfaz fluida para operaciones de bases de datos como la inseción, actualización, eliminación y recuperación de datos. También cuenta con elementos de protección contra ataques de inyección SQL. Está expuesto por la fachada DB
, un proxy estático para las clases de base de datos subyacentes en el contenedor de servicio.
Para comenzar, crearemos una variable de clase estática para contener todos los lugares de ejemplo que queramos insertar en la base de datos como matriz. Esto nos permitirá usar un bucle foreach
para iterar todos los valores, insertando cada uno en la base de datos con el generador de consultas.
Daremos a esta variable el nombre $places
:
<?php
use Illuminate\Database\Seeder;
class PlacesTableSeeder extends Seeder
{
static $places = [
'Berlin',
'Budapest',
'Cincinnati',
'Denver',
'Helsinki',
'Lisbon',
'Moscow',
'Nairobi',
'Oslo',
'Rio',
'Tokyo'
];
…
A continuación, tendremos que incluir una instrucción use
en la parte superior de nuestra clase PlacesTableSeeder
para facilitar la referencia a la fachada DB
en el código:
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class PlacesTableSeeder extends Seeder
…
Ahora, podemos iterar los valores de la matriz $places
usando un bucle foreach
e insertar cada uno en nuestra tabla places
con el generador de consultas:
…
public function run()
{
foreach (self::$places as $place) {
DB::table('places')->insert([
'name' => $place,
'visited' => rand(0,1) == 1
]);
}
}
El bucle foreach
itera cada valor de la matriz estática $places
. En cada iteración, usamos la fachada DB
para insertar una nueva fila en la tabla places
. Para el campo name
, fijamos el nombre del lugar que acabamos de obtener de la matriz $places
y para el campo visited
marcamos un valor aleatorio de 0
o 1
.
Así es como se visualizará la clase PlacesTableSeeder
completa después de todas las actualizaciones:
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class PlacesTableSeeder extends Seeder
{
static $places = [
'Berlin',
'Budapest',
'Cincinnati',
'Denver',
'Helsinki',
'Lisbon',
'Moscow',
'Nairobi',
'Oslo',
'Rio',
'Tokyo'
];
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
foreach (self::$places as $place) {
DB::table('places')->insert([
'name' => $place,
'visited' => rand(0,1) == 1
]);
}
}
}
Guarde y cierre el archivo cuando termine de realizar estos cambios.
Las clases de alimentadores no se cargan automáticamente en la aplicación. Debemos editar la clase principal DatabaseSeeder
para incluir una invocación al alimentador que acabamos de crear.
Abra el archivo database/seeds/DatabaseSeeder.php
con nano
o su editor favorito:
- nano database/seeds/DatabaseSeeder.php
La clase DatabaseSeeder
se parece a cualquier otro sembrador: deriva de la clase Seeder
y tiene un método run
. Actualizaremos este método para incluir una invocación a PlacesTableSeeder
.
Actualice el método actual run
dentro de su clase DatabaseSeeder
eliminando la línea marcada con comentarios y reemplazándola por el siguiente código resaltado:
…
public function run()
{
$this->call(PlacesTableSeeder::class);
}
...
Después de la actualización, la clase DatabaseSeeder
completa tendrá el siguiente aspecto:
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call(PlacesTableSeeder::class);
}
}
Guarde y cierre el archivo cuando termine de actualizar su contenido.
Con esto, terminamos de preparar una migración y un alimentador para nuestra tabla places
. En el siguiente paso, veremos la manera de ejecutarlos.
Antes de continuar, debemos asegurarnos de que su aplicación esté lista y en funcionamiento. Configuraremos la clave de cifrado de la aplicación y luego accederemos a esta última desde un navegador para probar el servidor web.
Para generar la clave de cifrado requerida por Laravel, puede usar el comando artisan key:generate
:
- docker-compose exec app php artisan key:generate
Una vez generada la clave, podrá acceder a la aplicación orientando su navegador al nombre de host o a la dirección IP de su servidor en el puerto 8000
:
http://server_host_or_ip:8000
Verá una página como la siguiente:
Esto significa que en la aplicación se puede establecer conexión con la base de datos, pero no se logró encontrar una tabla llamada places
. Ahora crearemos la tabla places
usando el siguiente comando migrate
de Artisan:
- docker-compose exec app php artisan migrate
Verá un resultado similar a este:
OutputMigration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.06 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
Migrating: 2020_02_10_144134_create_places_table
Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)
Observará que se ejecutaron algunas otras migraciones junto con la migración create_places_table
que configuramos. Estas migraciones se generan de forma automática cuando se instala Laravel. Aunque ahora no usaremos estas tablas adicionales, serán necesarias en el futuro cuando ampliemos la aplicación para tener usuarios registrados y tareas programadas. Por ahora, puede dejarlas como están.
En este momento, nuestra tabla sigue vacía. Debemos ejecutar el comando db:seed
para propagar la base de datos con nuestros lugares de ejemplo:
- docker-compose exec app php artisan db:seed
Con esto, se ejecutará nuestro alimentador y se insertarán los valores de ejemplo que definimos en nuestra clase PlacesTableSeeder
. Verá un resultado similar a este:
OutputSeeding: PlacesTableSeeder
Seeded: PlacesTableSeeder (0.06 seconds)
Database seeding completed successfully.
Ahora, vuelva a cargar la página de la aplicación en su navegador. Verá una página similar a la siguiente:
Cuando necesite comenzar desde cero, podrá descartar todas sus tablas de la base de datos con lo siguiente:
- docker-compose exec app php artisan db:wipe
OutputDropped all tables successfully.
Para ejecutar las migraciones de la aplicación y propagar las tablas con un solo comando, puede usar lo siguiente:
- docker-compose exec app php artisan migrate --seed
OutputMigration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.06 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
Migrating: 2020_02_10_144134_create_places_table
Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)
Seeding: PlacesTableSeeder
Seeded: PlacesTableSeeder (0.06 seconds)
Database seeding completed successfully.
Si quiere revertir una migración, puede ejecutar lo siguiente:
- docker-compose exec app php artisan migrate:rollback
Con esto, se activará el método down
para cada clase de migración dentro de la carpeta migrations
. Normalmente, se eliminarán todas las tablas que se crearon a través de las clases de migración y se dejarán solo las tablas que se puedan haber creado de forma manual. Verá resultados como este:
OutputRolling back: 2020_02_10_144134_create_places_table
Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds)
Rolling back: 2019_08_19_000000_create_failed_jobs_table
Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds)
Rolling back: 2014_10_12_000000_create_users_table
Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)
El comando rollback es especialmente útil cuando se realizan cambios en los modelos de la aplicación y no se puede usar un comando db:wipe
; por ejemplo, si varios sistemas dependen de la misma base de datos.
En esta guía, abordamos la forma de usar migraciones y alimentadores de bases de datos para facilitar la creación de bases de datos de desarrollo y la prueba de estas para una aplicación de Laravel 6.
Como paso siguiente, podría intereserle consultar la documentación de Laravel para obtener más información sobre cómo usar el generador de consultas y modelos de Eloquent para abstraer aún más el esquema de la base de datos de su aplicación.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!