Many-to-many Relationship with belongsToMany in Laravel
📖 Scenario: You are building a simple blog system where posts can have many tags, and tags can belong to many posts. This is a common real-world case where many items relate to many others.
🎯 Goal: Create a many-to-many relationship between Post and Tag models using Laravel's belongsToMany method. You will set up the data structure, configure the pivot table, define the relationship methods, and finally retrieve tags for a post.
📋 What You'll Learn
Create a pivot table migration named post_tag with post_id and tag_id columns
Define a tags method in the Post model using belongsToMany
Define a posts method in the Tag model using belongsToMany
Retrieve all tags for a given post using the tags relationship
💡 Why This Matters
🌍 Real World
Many web applications need to relate items in a many-to-many way, such as posts and tags, users and roles, or products and categories.
💼 Career
Understanding Laravel's many-to-many relationships is essential for backend developers working with databases and Eloquent ORM.
Progress0 / 4 steps
1
Create the pivot table migration
Create a migration file for the pivot table named post_tag with two unsigned big integer columns: post_id and tag_id. Use the Laravel schema builder to define these columns and set them as foreign keys referencing id on posts and tags tables respectively.
Laravel
Hint
Use Schema::create with a closure that receives $table. Add unsignedBigInteger columns for post_id and tag_id. Then add foreign key constraints referencing posts and tags tables.
2
Define the belongsToMany relationship in Post model
In the Post model, add a public method named tags that returns the result of calling belongsToMany(Tag::class). This sets up the many-to-many relationship from posts to tags.
Laravel
Hint
Inside the Post model class, define a public method tags that returns $this->belongsToMany(Tag::class).
3
Define the belongsToMany relationship in Tag model
In the Tag model, add a public method named posts that returns the result of calling belongsToMany(Post::class). This sets up the many-to-many relationship from tags to posts.
Laravel
Hint
Inside the Tag model class, define a public method posts that returns $this->belongsToMany(Post::class).
4
Retrieve tags for a post
Write code to retrieve all tags for a Post instance stored in a variable named $post. Use the tags relationship method to get the collection of tags and assign it to a variable named $tags.
Laravel
Hint
Use the tags property or method on the $post object to get all related tags and assign it to $tags.
Practice
(1/5)
1. What does the belongsToMany() method define in a Laravel model?
easy
A. A polymorphic relationship between models
B. A one-to-one relationship between two models
C. A one-to-many relationship from one model to another
D. A many-to-many relationship between two models
Solution
Step 1: Understand relationship types in Laravel
Laravel provides different methods to define relationships: one-to-one, one-to-many, many-to-many, and polymorphic.
Step 2: Identify the purpose of belongsToMany()
The belongsToMany() method specifically defines a many-to-many relationship where both models can have multiple related models.
Final Answer:
A many-to-many relationship between two models -> Option D
Quick Check:
belongsToMany() = many-to-many [OK]
Hint: belongsToMany means many-to-many link between models [OK]
Common Mistakes:
Confusing belongsToMany with hasOne or hasMany
Thinking it defines one-to-one relationships
Assuming it creates a polymorphic relation
2. Which of the following is the correct syntax to define a many-to-many relationship in a Laravel model named Post related to Tag?
easy
A. public function tags() { return $this->belongsToMany(Tag::class); }
B. public function tags() { return $this->hasMany(Tag::class); }
C. public function tags() { return $this->hasOne(Tag::class); }
D. public function tags() { return $this->morphToMany(Tag::class); }
Solution
Step 1: Recall the method for many-to-many relationships
In Laravel, many-to-many relationships use the belongsToMany() method inside the model.
Step 2: Match the syntax to the correct method
The correct syntax is public function tags() { return $this->belongsToMany(Tag::class); } to link Post and Tag models.
Final Answer:
public function tags() { return $this->belongsToMany(Tag::class); } -> Option A
Quick Check:
belongsToMany() syntax = public function tags() { return $this->belongsToMany(Tag::class); } [OK]
Hint: Use belongsToMany() for many-to-many syntax [OK]
Common Mistakes:
Using hasMany instead of belongsToMany
Using hasOne which is one-to-one
Confusing morphToMany with belongsToMany
3. Given the following code in a Laravel model User:
public function roles() {
return $this->belongsToMany(Role::class);
}
$user = User::find(1);
$roles = $user->roles()->pluck('name');
echo $roles->toJson();
What will be the output if user 1 has roles named "admin" and "editor"?
medium
A. Syntax error
B. ["1","2"]
C. ["admin","editor"]
D. null
Solution
Step 1: Understand the belongsToMany relationship usage
The roles() method returns all roles related to the user via the pivot table.
Step 2: Analyze the pluck and toJson methods
The pluck('name') extracts the 'name' field from each related role, returning a collection of role names. toJson() converts this collection to a JSON string.
5. You have two models, Student and Course, linked by a many-to-many relationship using a pivot table course_student. You want to attach a course with ID 5 to a student with ID 3 and also store the enrollment date in the pivot. Which code snippet correctly does this?
hard
A. $student = Student::find(3);
$student->courses()->attach(5, ['enrolled_at' => now()]);
B. $student = Student::find(3);
$student->courses()->save(5, ['enrolled_at' => now()]);
C. $student = Student::find(3);
$student->courses()->sync(5, ['enrolled_at' => now()]);
D. $student = Student::find(3);
$student->courses()->attach([5]);
Solution
Step 1: Understand attaching in many-to-many with pivot data
The attach() method adds a record to the pivot table and accepts the related model ID plus an array of extra pivot data.
Step 2: Analyze each option
$student = Student::find(3);
$student->courses()->attach(5, ['enrolled_at' => now()]); correctly uses attach(5, ['enrolled_at' => now()]). $student = Student::find(3);
$student->courses()->save(5, ['enrolled_at' => now()]); uses save() which expects a model instance, not an ID. $student = Student::find(3);
$student->courses()->sync(5, ['enrolled_at' => now()]); uses sync() incorrectly with extra data. $student = Student::find(3);
$student->courses()->attach([5]); attaches without pivot data.
Final Answer:
$student = Student::find(3);
$student->courses()->attach(5, ['enrolled_at' => now()]); -> Option A