Laravel relaciones muchos a muchos (Many to Many)

En este tutorial aprenderás cómo crear relaciones «muchos a muchos» (Many to Many) en Laravel. Este tipo de relaciones establecen una conexión entre dos modelos de datos (un modelo representa una tabla de la base de datos), en donde un registro en un modelo está relacionado con muchos registros en otro modelo y viceversa. Para contar con datos falsos de prueba usarás la librería de Laravel Faker y realizarás consultas de prueba con la herramienta Tinker, recuerda que al final encontrarás el repositorio de este tutorial. Sin más, manos a la obra.

Requisitos previos

  1.  Contar con un entorno de desarrollo como XAMPP, Wamp o Laragon.
  2.  Tener un proyecto Laravel conectado a una base de datos.
  3.  Editor de textos como VS Code o PHPStorm.

Planteamiento

Para este tutorial se usará de ejemplo un sistema que gestiona alumnos en una escuela, este sistema cuenta con dos modelos, Estudiante y Curso en donde un estudiante puede tener muchos cursos y un curso puede contar con muchos estudiantes. En este ejemplo aplica la relación de «muchos a muchos». En los siguientes pasos verás cómo implementar las relaciones «muchos a muchos» (Many to Many) en Laravel:

1. Crear modelos, migraciones y tabla intermedia

Cuando trabajas con relaciones de muchos a muchos es necesario crear una tabla intermedia o pivote la cual relaciona el id del modelo Estudiante y el id del modelo Curso. Primero crea el modelo Estudiante y su migración, para ello abre una terminal de comandos en la raíz de tu proyecto en Laravel y ejecuta la instrucción:

php artisan make:model Estudiante -m

Para crear el modelo Curso y su migración:

php artisan make:model Curso -m

Ahora para crear la tabla intermedia o tabla pivote recuerda que debe ser llamada como los modelos y en orden alfabético en este caso se llama curso_estudiante ya que curso es primero alfabéticamente que estudiante y siempre en singular. Ejecuta el siguiente comando:

php artisan make:migration create_curso_estudiante_table

2. Configurar migraciones

Con el editor de textos de tu preferencia abre el archivo database/migrations/…create_estudiantes_table.php y agrega el campo ‘name’ y ‘first_name’ para que quede así:

Schema::create('estudiantes', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('last_name');
        $table->timestamps();
});

Toca configurar el archivo database/migrations/…create_cursos_table.php al cual para este ejemplo solo le agregarás el campo ‘name’:

Schema::create('cursos', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
});

Ahora abre el archivo database/migrations/…create_curso_estudiante_table.php que es la tabla intermedia en donde se crearán las relaciones con las tablas cursos y estudiantes:

Schema::create('curso_estudiante', function (Blueprint $table) {
        $table->id();

        $table->unsignedBigInteger('curso_id');
        $table->foreign('curso_id')->references('id')->on('cursos')->onDelete('cascade');

        $table->unsignedBigInteger('estudiante_id');
        $table->foreign('estudiante_id')->references('id')->on('estudiantes')->onDelete('cascade');

        $table->timestamps();
});

En el anterior código el método unsignedBigInteger() asigna al campo curso_id un tipo de dato entero, positivo y soporta un valor muy grande. El método foreign() define la llave foránea y la relación entre los campos curso_id de la tabla curso_estudiante y el campo id de la tabla cursos.

3. Relacionar los modelos Estudiante y Curso

Toca crear las relaciones entre Estudiante y Curso a nivel de modelo, para ello abre el archivo app/Models/Estudiante.php y como un estudiante puede tener muchos cursos se usa el método en plural y se utiliza belongsToMany(). Agrega la función estudiantes() al archivo:

//Relationships Many to Many
public function cursos(){
    return $this->belongsToMany(Curso::class, 'curso_estudiante');
}

Para terminar de crear la relación a nivel modelo abre el archivo app/Models/Curso.php y como un curso puede pertenecer a muchos estudiantes el nombre del método debe estar en plural y al igual que el método anterior se usa belongsToMany():

//Relationships Many to Many
public function estudiantes(){
    return $this->belongsToMany(Estudiante::class, 'curso_estudiante');
}

4. Agregar datos de prueba

Para generar datos falsos de prueba voy a usar Factories para poblar las tablas de la base de datos, para crear el factory para el modelo Estudiante ejecuta la siguiente instrucción en la consola de comandos:

php artisan make:factory EstudianteFactory

Ahora para crear el factory para el modelo Curso:

php artisan make:factory CursoFactory

4.2 Configurar EstudianteFactory

Abre el archivo database/factories/EstudianteFactory.php y para agregar información falsa de prueba vas utilizar la librería Faker de Laravel para lo cual pega el siguiente código en tu archivo:

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Estudiante>
 */
class EstudianteFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
             'name' => $this->faker->name(),
             'last_name' => $this->faker->lastName(),
        ];
    }
}

4.3 Configurar CursoFactory

En el archivo database/factories/CursoFactory.php dentro del método definition() en el array return agrega la siguiente línea de código para generar los nombres falsos para los cursos:

'name' => $this->faker->sentence(2)

4.3 Configurar archivo DatabaseSeeder

Abre el archivo database/seeders/DatabaseSeeder.php y al inicio importa los modelos Estudiante y Curso:

use App\Models\Curso;
use App\Models\Estudiante;

El siguiente código es un factory que crea datos falsos de prueba haciendo uso de las relaciones «muchos a muchos» (Many to Many) en Laravel, crea 15 estudiantes, 8 cursos y cada curso es tomado 3 estudiantes con los cuales son relacionados en la tabla intermedia. Dentro del método run() agrega las siguiente líneas de código:

//Se crean 15 estudiantes
    Estudiante::factory()->times(15)->create();
    //Se crean 8 cursos
    Curso::factory()->times(8)->create()->each( function($curso){
        $curso->estudiantes()->sync(
            //Cada curso es tomado por 3 estudiantes
            Estudiante::all()->random(3)
        );
});

Para correr las migraciones y poblar las tablas ejecuta la siguiente instrucción:

php artisan migrate:fresh --seed

Abre tu cliente de gestión de base de datos como PHPMyAdmin, Heidi o MySQLWorkbench y verás que las tablas estudiantes y cursos se han poblado de datos y en la tabla intermedia o pivote están las relaciones de cursos y estudiantes a través de su id.

5. Probar las relaciones muchos a muchos (Many to Many) en Laravel

Laravel como el gran marco de desarrollo que es cuenta con un buen número de herramientas que facilitan el trabajo y Tinker es una de ellas. Con Tinker harás consultas desde la terminal de comandos para probar las relaciones en la base de datos y modelos, para llamar a Tinker ejecuta la instrucción:

php artisan tinker

Para consultar todos los registros de los estudiantes escribe:

Estudiantes::all();

Si quieres ver todos los cursos que se han registrado en la base de datos ejecuta la instrucción:

Cursos::all();

Ahora consulta un estudiante en específico como el que tiene el id 11:

$estudiante = Estudiante::find(11);

Consulta los cursos a los que el estudiante de id 11 está inscrito ejecutando:

$estudiante->cursos

Para ver los estudiantes que están inscritos en un curso específico:

$curso = Curso::find(5);

Accediendo a través de la relación muchos a muchos:

$curso->estudiantes

Se muestran todos los estudiantes que pertenecen a este curso. Las relaciones de las tablas están funcionando correctamente a nivel base de datos y a nivel modelos.

Conclusión

En este tutorial aprendiste que son y cómo implementar las relaciones muchos a muchos (Many to Many) en Laravel. Si ha sido de ayuda te invito a compartirlo en tus redes sociales para llegar a más personas y si tienes dudas o comentarios déjalos en la caja de comentarios estaré al pendiente de ellos. Saludos.

Referencias: Documentación Laravel.

Repositorio del proyecto.

8 COMENTARIOS

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.