How to Use a Many-to-Many Relationship in Laravel

Many-to-Many relationships are commonly used in applications to link 2 or more entities through a pivot table. In this blog post, I’ll demonstrate how a Many-to-Many relationship is set up and accessed using Laravel Eloquent.

To use a Many-to-Many relationship in Laravel we need to define a belongsToMany method in each of the Models involved, along with a pivot table to connect the two tables that follow Laravel’s naming convention. For example, the pivot of the tables students and courses should be named course_student.

While I wouldn’t recommend it, it is possible to use a naming that is different from the Laravel naming convention. We’ll show this in step 2

Diagram Showing the Tables students and courses and their pivot course_student

In the following step-by-step guide, we’ll see exactly how this can be implemented and how we can create data that is related by a Many-to-Many and access it.

Let’s get started!

Step 1: Creating and Running the Migrations

To begin, let’s create the necessary migrations for the “students” and “courses” tables, as well as the pivot table “course_student”. Open your terminal and run the following Artisan commands:

php artisan make:migration create_students_table --create=students
php artisan make:migration create_courses_table --create=courses
php artisan make:migration create_course_student_table --create=course_student

This will generate three migration files: one for the “students” table, one for the “courses” table, and one for the pivot table “course_student”. Open each of the generated migration files and modify their up() and down() methods as shown below:

For the students table, use:

database/migrations/2023_06_27_190119_create_students_table.php
<?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('students', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('students');
    }
};

For the courses table, use:

database/migrations/2023_06_27_190119_create_students_table.php
<?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('courses', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('description')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('courses');
    }
};

For the course_student pivot table, use:

database/migrations/2023_06_27_200430_create_course_student_table.php
<?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('course_student', function (Blueprint $table) {
            $table->id();
            $table->foreignIdFor(\App\Models\Student::class);
            $table->foreignIdFor(\App\Models\Course::class);
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('course_student');
    }
};

Please note that the course_student table contains only the essential fields to establish the relation (2 foreign key values). However, it is possible to include additional fields which can be useful. For instance, you could add an enrollment_date column to store the date when a student enrolls for the course. To learn more about adding and accessing extra fields in a pivot table with Laravel’s belongsToMany relationship, you can read my post: Using Extra Fields in Pivot Table With Laravel belongsToMany.

After saving the modified migration files, run the following command to create the tables:

php artisan migrate

Step 2: Creating the Eloquent Models

Next, let’s create the Eloquent models for the “Student” and “Course” entities. Run the following commands in your terminal:

php artisan make:model Student
php artisan make:model Course

This will generate two model files in the “app/Models” directory.

Note: In this case, we do not need to create a model for the intermediate pivot table “course_student” since it does not require additional functionality beyond the relationship.

Open the generated model files and add the necessary relationships as shown below.

For the Student Model, use:

app/Models/Student.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Student extends Model
{

    public function courses()
    {
        return $this->belongsToMany(Course::class);
    }
}

For the Course Model, use:

app/Models/Course.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Course extends Model
{
    public function students()
    {
        return $this->belongsToMany(Student::class);
    }
}

It’s worth noting that you can customize the pivot table name if necessary. By providing a second parameter to the belongsToMany method, you can specify a different name for the pivot table. For example, you can use return $this->belongsToMany(Student::class, 'courses_students'); to define a custom pivot table named “courses_students”. This flexibility allows you to choose a pivot table name that aligns with your specific needs.

Step 3: Performing Many-to-Many Queries

Now that we have set up the migrations and models, we can perform queries to retrieve and manipulate data using the many-to-many relationship. Here are a few examples of how you can use the relationship:

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('/many-to-many', function () {
    // Create a new student
    $student = new \App\Models\Student();
    $student->name = 'John Doe';
    $student->save();

    // Create a new course
    $course = new \App\Models\Course();
    $course->title = 'Introduction to Laravel';
    $course->description = 'Introduction to Laravel';
    $course->save();

    // Associate a student with a course
    $student->courses()->attach($course);

    // Retrieve courses for a student
    $student = \App\Models\Student::find(1);
    $courses = $student->courses;
    dump($courses);

    // Retrieve students for a course
    $course = \App\Models\Course::find(1);
    $students = $course->students;
    dump($students);
});

In a Many-to-Many relationship in Laravel Eloquent, you can associate a model with a related model by calling the attach() method. For example, $student->courses()->attach($course) establishes a connection between the $student model and the $course model, creating a record in the pivot table.

After running our queries the database contains the following records:

Showing Result Data in students, courses, and student_courses Tables Using MySQL Client

Further Many-to-Many Examples

In addition to the “Student”, and “Course” entities and their pivot table, we have used in this tutorial, there are various other scenarios where the Many-to-Many relationship can be applied. Here are a few more examples:

ExampleModel 1Pivot TableModel 2
1Useruser_roleRole
2Productcategory_productCategory
3Studentcourse_studentCourse
4Actormovie_actorMovie
5Authorbook_authorBook
6Teamplayer_teamPlayer
7Recipeingredient_recipeIngredient
Table Showing Examples of Entities Suited for a Many-to-Many Relationship

By understanding the concept of Many-to-Many relationships in Laravel, you can effectively manage you can easily manage complex relationships and retrieve data from related models.

Conclusion

In this tutorial, we have learned how to set-up a Many-to-Many relationship by creating the necessary migrations for the tables students, courses and their pivot table course_student, and the Eloquent models for the Student and Course entities.

We have also seen how to perform Many-to-Many queries, such as associating a student with a course using the attach() method and retrieving related data.

By following these steps, you can effectively establish and manage Many-to-Many relationships in your Laravel applications.

Finally, we included some example entities to which you might apply a Many-to-Many Relationship, as an inspiration. Happy coding!

References:

Johan van den Broek

Johan is the creator of laracoding.com. As a child, he began tinkering with various programming languages, many of which have been long forgotten today. Currently, he works exclusively with PHP and Laravel, and his passion for programming remains to this day.

2 thoughts on “How to Use a Many-to-Many Relationship in Laravel

  1. Johan’s pages on Larvel consistently are beautifully clear, methodical, concise and get to the core of what one needs to know. Always find myself coming back to them. Keep up the good work!

    1. Thanks so much for taking the time to leave me this wonderful compliment! It really means a lot to me. If you ever have any questions or suggestions, feel free to reach out.

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts