📡 You're offline — showing cached content
New version available!
Quick Access
JavaScript Intermediate Featured

Laravel Eloquent ORM: Relationships, Eager Loading and Query Builder

Master Laravel Eloquent — all relationship types, solving the N+1 query problem with eager loading, scopes, mutators and advanced query builder.

EzyCoders Admin January 22, 2026 15 min read 32 views
Laravel Eloquent ORM Complete Guide
Share: Twitter LinkedIn WhatsApp

Eloquent ORM

Eloquent makes database interactions expressive and object-oriented. Understanding eager loading and relationships is critical — it directly impacts your application's query performance.

Model Definition

<?php
use Illuminate\Database\Eloquent\Model;

class Post extends Model {
    protected $fillable = ['title', 'content', 'user_id', 'status'];
    protected $casts    = [
        'is_published' => 'boolean',
        'published_at' => 'datetime',
        'meta'         => 'array',
    ];

    // Local scope — reusable query constraint
    public function scopePublished($query) {
        return $query->where('status', 'published');
    }
}

Relationships

<?php
class User extends Model {
    public function profile()  { return $this->hasOne(Profile::class); }
    public function posts()    { return $this->hasMany(Post::class); }
    public function roles()    { return $this->belongsToMany(Role::class)->withPivot('assigned_at'); }
    public function comments() { return $this->hasManyThrough(Comment::class, Post::class); }
}

class Post extends Model {
    public function user() { return $this->belongsTo(User::class); }
    public function tags() { return $this->belongsToMany(Tag::class)->withTimestamps(); }
}

N+1 Problem and Eager Loading

<?php
// BAD — 1 + N queries (N = number of posts)
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name; // new query each iteration!
}

// GOOD — always 2 queries regardless of post count
$posts = Post::with('user')->get();
foreach ($posts as $post) {
    echo $post->user->name; // no extra queries
}

// Load multiple relationships
$posts = Post::with(['user', 'tags', 'comments.user'])->get();

// Conditional eager loading
$posts = Post::with(['comments' => function($q) {
    $q->where('approved', true)->latest();
}])->get();

Query Builder

<?php
// Chaining conditions
$users = User::where('active', 1)
             ->whereIn('role', ['admin', 'editor'])
             ->whereNotNull('email_verified_at')
             ->orderBy('name')
             ->paginate(15);

// Aggregate
$stats = Post::selectRaw('category_id, COUNT(*) as total, AVG(views) as avg_views')
             ->where('status', 'published')
             ->groupBy('category_id')
             ->having('total', '>', 5)
             ->get();

// Subquery — users with 10+ published posts
$topAuthors = User::whereHas('posts', function($q) {
    $q->where('status', 'published');
}, '>=', 10)->get();

Q: What is the N+1 query problem?

When you load N records then execute 1 additional query per record for a relationship, resulting in N+1 total queries. For 100 posts, that is 101 queries instead of 2. Solve it with with() for eager loading.


Q: Difference between hasMany and belongsToMany?

hasMany is a one-to-many relationship with a foreign key on the child table. belongsToMany uses a pivot/junction table for many-to-many. A user hasMany posts (user_id on posts table) but belongsToMany roles (user_role pivot table).

EzyCoders Admin
Written by
EzyCoders Admin

Team Lead and Full-Stack Developer with experience in PHP, JavaScript, SQL, DSA, and System Design. Passionate about software engineering, scalable web technologies, and helping developers prepare for coding interviews and tech careers through practical tutorials and professional guidance.

Comments (0)

No comments yet. Be the first!

Leave a Comment