Kritim Yantra
Mar 25, 2025
Eloquent ORM (Object-Relational Mapping) is one of Laravel's most powerful features, allowing developers to interact with databases using an expressive, fluent syntax. One of the key strengths of Eloquent is its ability to define and manage relationships between database tables effortlessly.
In this blog post, we'll explore Laravel 12 Eloquent Relationships in detail, covering all types of relationships with practical examples.
Database relationships define how tables interact with each other. In Laravel, Eloquent provides a simple way to define these relationships using model classes.
Relationships allow you to:
Laravel supports several types of relationships:
A one-to-one relationship links one record in a table to exactly one record in another table.
Example: A User
has one Profile
.
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('bio');
$table->timestamps();
});
// User Model
public function profile() {
return $this->hasOne(Profile::class);
}
// Profile Model
public function user() {
return $this->belongsTo(User::class);
}
$user = User::find(1);
$profile = $user->profile; // Gets the user's profile
A one-to-many relationship links one record to multiple records in another table.
Example: A Post
has many Comments
.
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained();
$table->text('content');
$table->timestamps();
});
// Post Model
public function comments() {
return $this->hasMany(Comment::class);
}
// Comment Model
public function post() {
return $this->belongsTo(Post::class);
}
$post = Post::find(1);
$comments = $post->comments; // Gets all comments for the post
A many-to-many relationship requires an intermediate pivot table.
Example: A User
can belong to many Roles
, and a Role
can have many Users
.
Schema::create('role_user', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
$table->foreignId('role_id')->constrained();
$table->primary(['user_id', 'role_id']);
});
// User Model
public function roles() {
return $this->belongsToMany(Role::class);
}
// Role Model
public function users() {
return $this->belongsToMany(User::class);
}
$user = User::find(1);
$roles = $user->roles; // Gets all roles of the user
This relationship allows accessing a distant relation via an intermediate model.
Example: A Supplier
has one History
through a User
.
Schema::create('suppliers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->foreignId('supplier_id')->constrained();
$table->string('name');
$table->timestamps();
});
Schema::create('histories', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('details');
$table->timestamps();
});
// Supplier Model
public function history() {
return $this->hasOneThrough(History::class, User::class);
}
$supplier = Supplier::find(1);
$history = $supplier->history; // Gets the supplier's history via user
Similar to hasOneThrough
, but retrieves multiple records.
Example: A Country
has many Posts
through Users
.
Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->foreignId('country_id')->constrained();
$table->string('name');
$table->timestamps();
});
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('title');
$table->timestamps();
});
// Country Model
public function posts() {
return $this->hasManyThrough(Post::class, User::class);
}
$country = Country::find(1);
$posts = $country->posts; // Gets all posts from users in the country
A polymorphic relationship allows a model to belong to multiple other models on a single association.
Example: Comments
can belong to Posts
or Videos
.
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('content');
$table->morphs('commentable'); // Adds commentable_id and commentable_type
$table->timestamps();
});
// Comment Model
public function commentable() {
return $this->morphTo();
}
// Post Model
public function comments() {
return $this->morphMany(Comment::class, 'commentable');
}
// Video Model
public function comments() {
return $this->morphMany(Comment::class, 'commentable');
}
$post = Post::find(1);
$comments = $post->comments; // Gets all comments for the post
A more advanced polymorphic relationship where multiple models can have many related models.
Example: Posts
and Videos
can have many Tags
.
Schema::create('taggables', function (Blueprint $table) {
$table->foreignId('tag_id')->constrained();
$table->morphs('taggable'); // taggable_id, taggable_type
});
// Tag Model
public function posts() {
return $this->morphedByMany(Post::class, 'taggable');
}
public function videos() {
return $this->morphedByMany(Video::class, 'taggable');
}
// Post Model
public function tags() {
return $this->morphToMany(Tag::class, 'taggable');
}
// Video Model
public function tags() {
return $this->morphToMany(Tag::class, 'taggable');
}
$post = Post::find(1);
$tags = $post->tags; // Gets all tags for the post
All relationships in Laravel are defined as methods in Eloquent models. The method names should be descriptive (e.g., posts()
, comments()
).
You can query relationships like regular methods:
// Get all posts with at least one comment
$posts = Post::has('comments')->get();
// Get posts with more than 5 comments
$posts = Post::has('comments', '>', 5)->get();
// Filter using whereHas
$posts = Post::whereHas('comments', function ($query) {
$query->where('content', 'like', '%awesome%');
})->get();
Eager loading prevents the N+1 query problem by loading relationships in advance.
// Without Eager Loading (N+1 Problem)
$posts = Post::all();
foreach ($posts as $post) {
echo $post->comments->count(); // Queries the DB each time
}
// With Eager Loading (Optimized)
$posts = Post::with('comments')->get();
foreach ($posts as $post) {
echo $post->comments->count(); // No additional queries
}
You can attach related models easily:
// One-to-Many
$post = Post::find(1);
$comment = $post->comments()->create(['content' => 'Great post!']);
// Many-to-Many
$user = User::find(1);
$user->roles()->attach([1, 2]); // Attach role IDs
Laravel Eloquent Relationships provide a clean, expressive way to handle database associations. Whether you're working with one-to-one, one-to-many, many-to-many, or polymorphic relationships, Eloquent makes it easy to define, query, and manage them efficiently.
By mastering these relationships, you can build complex database interactions with minimal effort while keeping your code clean and maintainable.
🚀 Happy Coding with Laravel 12! 🚀
No comments yet. Be the first to comment!
Please log in to post a comment:
Continue with Google