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).
Comments (0)
No comments yet. Be the first!
Leave a Comment