Novedades de Laravel 7

Laravel 7 incluye 2 nuevos métodos id() y foreignId() que tienen como objetivo simplificar la manera en la que definimos las columnas de llaves primarias y foráneas de nuestras aplicaciones mediante el sistema de migraciones, como veremos a continuación.

Aprende más sobre bases de datos y SQL con nuestro libro digital disponible en Leanpub con 40% de descuento.

Ver más

El 8 de noviembre de 2018 Basecamp estuvo en modo de solo lectura por varias horas ¿La razón? Se quedaron sin enteros, puesto que en su base de datos definían todas las llaves primarias como tipo INT en vez de BIGINT. INT era el tipo por defecto en Rails hasta hace unos años, también era el tipo por defecto en Laravel hasta la versión 5.7.

A partir de Laravel 5.8 se sugiere usar el tipo BIGINT por defecto en el sistema de migraciones mediante el método bigIncrements:

<?php

//...

class CreateUsersTable extends Migration
{
    /**/
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');  // <--- AQUI
            
            //...
        });
    }
    
    //...
}

Este cambio hizo que definir llaves foráneas se hiciera más engorroso, por ejemplo, imagina que queremos agregar una llave foránea user_id a la tabla de posts que creamos en la lección pasada:

<?php

//...

class CreatePostsTable extends Migration
{
    /**/
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            //...

            $table->unsignedBigInteger('user_id'); // UNSIGNED BIG INT
            $table->foreign('user_id')
                ->references('id')
                ->on('users');

            //...
        });
    }

//...

}

Nota que el método unsignedBigInteger es un poco largo.

Ahora en Laravel 7 lo anterior se logra con muchos menos caracteres.

Definiendo llaves primarias y foráneas en Laravel 7

La llave primaria se puede definir usando el método id:

<?php

//...

class CreateUsersTable extends Migration
{
    /**/
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id(); // <-- AQUI

            //...
        });
    }

    //...
}

Este método creará una llave primaria autoincremento con el nombre id y de tipo BIGINT sin signo (UNSIGNED).

Podemos crear una llave foránea en la tabla de posts que apunte a la tabla de usuarios de esta forma:

<?php

//...

class CreatePostsTable extends Migration
{
    /**/
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            //...

            $table->foreignId('user_id') // UNSIGNED BIG INT
                ->references('id')
                ->on('users'); 
           
            //...
        });
    }

//...

}

Este llamado al método foreignId definirá una columna llamada user_id de tipo entero grande sin signo (BIGINT UNSIGNED) en la tabla de posts.

Además con el uso de references y on estamos definiendo la restricción para que todos los valores de esta columna user_id deban corresponderse a IDs que existan en la tabla de usuarios (users).

Además, en caso de que cumplamos con las siguientes convenciones:

  1. Las tablas y columnas están definidas en inglés
  2. Las tablas están en plural (users, posts)
  3. Las llaves primarias se llaman id
  4. Las columnas que representan llaves foráneas llevan el nombre de la tabla a la que hacen referencia en singular seguido del sufijo _id (por ejemplo, como la tabla se llama users la llave foránea será users en singular + _id es decir user_id).

Podemos resumir la definición aún más usando el método constrained:

<?php

//...

Schema::create('posts', function (Blueprint $table) {
    //...

    $table->foreignId('user_id') // UNSIGNED BIG INT
        ->constrained();  // <-- DEFINE LA RESTRICCION DE LLAVE FORANEA
           
    //...
});

A esto podemos encadenar el llamado a onDelete para que si un usuario es eliminado sus posts queden sin autor o sean eliminados:

<?php

//...

Schema::create('posts', function (Blueprint $table) {
    //...

    $table->foreignId('user_id') // UNSIGNED BIG INT
        ->nullable() // <-- IMPORTANTE: LA COLUMNA DEBE ACEPTAR NULL COMO VALOR VALIDO
        ->constrained()  // <-- DEFINE LA RESTRICCION DE LLAVE FORANEA
        ->onDelete('SET NULL'); // <-- AL ELIMINAR UN USUARIO SUS POSTS QUEDARAN SIN AUTOR
    //...
});

Espero que estos sencillos métodos adicionales te ayuden a definir tus tablas más rápidamente a partir de la versión 7 del framework Laravel. Únete a nuestro listado de correos para obtener más información sobre nuevas lecciones, promociones, y más:

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Enlace de modelos a rutas en Laravel 7 Lección siguiente Creación de un componente de campo de texto con Blade y Laravel 7