Crear una migración con Artisan

¿Qué son las migraciones?

En Laravel se pueden usar las migraciones para facilitarnos el trabajo de definir y modificar las tablas de nuestra la base de datos.

Una migración es una clase PHP que contiene la información necesaria para crear, borrar y modificar las tablas y campos de la base de datos.

Lo bueno que tienen es que podemos compartirlas con otros desarrolladores del proyecto y así todos tendremos la misma versión de la base de datos. Por ejemplo, si un nuevo desarrollador llega al proyecto solo tiene que hacer:

$ php artisan migrate

y ya tendrá la estructura de la base de datos exactamente igual que el resto de miembros del equipo. Y será la misma base de datos que en los servidores de prueba y producción (si éstos también usan migraciones, claro).

También nos permite hacer control de versiones en la base de datos. Podemos deshacer cambios, volver a un estado anterior de la base de datos, etc.

¿Cuándo no debo usar migraciones?

Las migraciones se pueden deshacer o se pueden rehacer por completo. El peligro de estas dos acciones es que pueden (y seguramente lo harán) borrar o vaciar tablas. Esto es algo que nunca jamás querremos hacer en un servidor de producción. Podríamos perder nuestros datos... y nuestro trabajo.

Así que mucho cuidado al trabajar con migraciones en un servidor de producción. Afortunadamente, Artisan (la herramienta que nos permite usar las migraciones), nos avisa antes de ejecutar una migración de este tipo cuando estamos en un servidor de producción. Aún así mucho cuidado.

Requisitos

  • Tener instalada y configurada una aplicación con Laravel. Este artículo está escrito usando la versión 5.3 pero lo que se menciona debería poder aplicarse a versiones anteriores.
  • Tener instalado y configurado para tu aplicación Laravel un servidor de bases de datos (o SQLite). Para el artículo estoy usando un servidor MySQL.
  • Para este artículo estoy suponiendo que estás usando Homestead para tu desarrollo. Si no lo conoces te recomiendo que lo pruebes.

Crear una migración con artisan

Si estás usando la máquina virtual Homestead abre un terminal y teclea:

$ homestead ssh

y vete a la carpeta del proyecto.

NOTA: Si no usas Homestead abre un terminal y vete a la carpeta que contiene tu proyecto.

Una vez en la carpeta de proyecto teclea:

$ php artisan make:migration crear_tabla_noticias

Este comando creará una fichero de migración en blanco que se guardará en la carpeta database/migrations.

El nombre de la migración debería darnos pistas de lo que hace la migración. Además, es el que se usa para generar el nombre de la clase. En este caso la clase se llamará: CrearTablaNoticias.

El fichero creado tendrá un nombre similar a:

2016_07_28_061605_crear_tabla_noticias.php

Al principio se añade la fecha para que artisan sepa en qué orden tiene que procesar los archivos.

Abre el archivo y verás que se ha generado con dos únicos métodos: up y down.

El método up es el que se ejecuta cuando se hace una migración y el método down cuando se deshace.

El siguiente paso es meter el código en la función up(). En este ejemplo vamos a crear una tabla llamada series que tendrá un campo id (que será de tipo entero y los valores se auto incrementarán), un campo 'name' de 30 caracteres y un campo 'description' de 255 caracteres:

public function up()
{
    Schema::create('series', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name', 30);
    $table->string('description');
    $table->timestamps();
    });
}

Lo de timestamps() hace que se generen dos campos adicionales 'created_at' y 'updated_at'. Éstos son opcionales pero suelen estar bien si queremos tener un registro de cuándo se ha creado un registro o cuándo se ha modificado. El trabajo de actualizar los campos created_at y updated_at nos lo hace Laravel automáticamente (si usamos Eloquent).

En la función down() vamos a meter el código que se va a ejecutar cuando deshagamos (si es que la deshacemos) la migración:

public function down()
{
    Schema::drop('series');
}

En este caso lo que se hace es borrar la tabla series.

Una vez hemos terminado con la migración podemos ejecutarla (dento del terminal en el que estamos conectados al Homestead:
$ php artisan migrate

Y el resultado sería:

Migrated: 2016_07_28_061605_create_series_table

Si ahora nos conectamos al servidor MySQL podremos comprobar que se ha creado la tabla con la escritura deseada:

$ mysql -uhomestead -p
(si no has cambiado nada en Homestead la clave debería ser “secret”)
mysql> use homestead;
mysql> show create table series;
series | CREATE TABLE `series` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Deshacer una migración

Antes hemos visto que Artisan nos genera también un método llamado down():

public function down()
{
    Schema::drop('series');
}

También he comentado que las migraciones se pueden deshacer. Cuando una migración se deshace se ejecuta el método down(). En este caso este método borraría la tabla que hemos creado.

Para deshacer la migración:

$ php artisan migrate:rollback

También podemos deshacer todas las migraciones de golpe con:

$ php artisan migrate:reset

Con este comando lo que sucederá es que se borrarán y volverán a crear todas las tablas de la base de datos. Y, claro, perderemos todos los datos.

Estos son los comandos que he mencionado que son muy peligrosos en un servidor de producción.

¿Qué migraciones se deshacen con migrate:rollback?

Cada vez que ejecutamos el comando migrate:

$ php artisan migrate

Se buscan todas las migraciones que están pendientes de ser procesadas desde la última vez que ejecutamos las migraciones.

Imaginemos que, por ejemplo, tenemos en nuestro proyecto diez ficheros de migraciones pero seis de ellas ya las habíamos procesado anteriormente. Si ahora ejecutamos el comando migrate solo se van a procesar la cuatro que estaban pendientes.

Por tanto, si deshacemos la última migración solo se desharán estas cuatro últimas. Si volvemos a ejecutar el comando migrate:rollback se deshará la migración anterior, es decir se desharán los seis ficheros de migración iniciales.

Modificar campos

Una migración no tiene por qué crear/borrar una tabla. También puede modificarla. Podemos añadir nuevos campos, borrarlos, cambiar tu tipo, su longitud, modificar índices, etc.

Crear una columna nueva

Para crear una columna nueva basta con usar el método table y pasarle la lista de los campos que queremos crear:

Schema::table('users', function ($table) {
    $table->string('email');
});

Cambiar una columna

Para poder modificar columnas debemos añadir una nueva dependencia a nuestro proyecto:

$ composer require doctrine/dbal

NOTA: Ejecuta este comando en un terminal desde la carpeta de tu proyecto Laravel.

Una vez instalado el paquete doctrine/dbal puedes modificar las columnas de tus tablas:

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

O podemos renombarlas:

Schema::table('users', function ($table) {
    $table->renameColumn('nombreOriginal', 'nuevoNombre');
});

O borrarlas:

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

O borrar varias de golpe pasando un array en lugar de un único nombre de columna:

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

NOTA: Esta última opción parece no funcionar si se usa SQLite.

Más información

En la documentación oficial de Laravel 5.3 tienes información completa de los métodos que hay disponibles para la creación y la modificación de las tablas. Te recomiendo que eches un vistazo.

Autor:
Nivel: Intermedio
Palabras clave:
Fecha publicado:
Fecha actualizado: 21-09-2016

Otros capítulos de la misma serie

Este capítulo es parte de la serie: Laravel pearls.

Y muchos más en preparación.

Disponible en los planes: Laravel hero