Buat kamu yang belajar Laravel, menguasai query database itu penting banget. Kalau query-nya ngasal, aplikasi bisa jadi lemot dan bikin user kesal. Laravel Eloquent memang mudah dipakai, tapi tetap harus tahu cara yang benar.
Dari pengalaman ngoding Laravel, ada 10 query dasar yang sering banget dipake dan wajib dikuasai. Ini bukan cuma soal nulis kode, tapi juga kapan harus pakai yang mana.
Yuk kita bahas satu-satu dengan contoh sederhana yang bisa langsung dicoba!
Eager Loading - Cara Ambil Data Relasi yang Benar
Query pertama yang harus dikuasai adalah eager loading. Ini buat ngambil data yang punya relasi tanpa bikin database kewalahan.
Masalah yang Sering Terjadi
// ❌ Cara yang salah - bikin database kerja keras
$posts = Post::all();
foreach ($posts as $post) {
echo $post->user->name; // Tiap post query database lagi
}
Kalau ada 100 post, database akan diquery 101 kali! (1 kali ambil posts + 100 kali ambil user)
Cara yang Benar
// ✅ Pakai with() - cuma 2 kali query
$posts = Post::with('user')->get();
foreach ($posts as $post) {
echo $post->user->name; // Data user udah ada
}
Ambil Banyak Relasi Sekaligus
// Ambil post sama user dan category-nya
$posts = Post::with(['user', 'category'])->get();
Ambil Relasi Bersyarat
// Cuma ambil user yang aktif
$posts = Post::with(['user' => function ($query) {
$query->where('status', 'active');
}])->get();
Dengan eager loading, aplikasi jadi lebih cepat karena database gak perlu kerja berkali-kali.
Scopes - Bikin Query yang Bisa Dipakai Berulang
Scopes itu kayak shortcut buat query yang sering dipake. Jadi gak perlu nulis ulang terus-terusan.
Buat Scope di Model
class Post extends Model
{
// Scope buat post yang udah dipublish
public function scopePublished($query)
{
return $query->where('status', 'published');
}
// Scope buat post dari author tertentu
public function scopeByAuthor($query, $authorId)
{
return $query->where('user_id', $authorId);
}
// Scope buat post terbaru
public function scopeRecent($query, $days = 7)
{
return $query->where('created_at', '>=', now()->subDays($days));
}
}
Cara Pakai Scope
// Pakai satu scope
$posts = Post::published()->get();
// Gabung beberapa scope
$posts = Post::published()
->recent(30)
->byAuthor(1)
->get();
// Gabung dengan where biasa
$posts = Post::published()
->where('category_id', 2)
->orderBy('created_at', 'desc')
->get();
Scope yang Fleksibel
public function scopeFilter($query, $filters)
{
if (isset($filters['status'])) {
$query->where('status', $filters['status']);
}
if (isset($filters['search'])) {
$query->where('title', 'like', '%' . $filters['search'] . '%');
}
if (isset($filters['category'])) {
$query->where('category_id', $filters['category']);
}
return $query;
}
// Cara pakai
$posts = Post::filter(request()->only('status', 'search', 'category'))->get();
Dengan scope, kode jadi lebih rapi dan gak perlu copy-paste query yang sama.
Query Hitung-hitungan untuk Dashboard
Query ini berguna buat bikin dashboard atau laporan sederhana.
Hitung Data Dasar
// Hitung jumlah post
$totalPosts = Post::count();
// Hitung post yang dipublish
$publishedPosts = Post::where('status', 'published')->count();
// Jumlah total views
$totalViews = Post::sum('view_count');
// Rata-rata rating
$averageRating = Review::avg('rating');
// Post tertua dan terbaru
$oldestPost = Post::min('created_at');
$newestPost = Post::max('created_at');
Kelompokkan Data
// Hitung post per kategori
$postsByCategory = Post::select('category_id')
->selectRaw('count(*) as total')
->groupBy('category_id')
->get();
// Penjualan per bulan
$monthlySales = Sale::selectRaw('MONTH(created_at) as month')
->selectRaw('SUM(amount) as total')
->groupBy('month')
->get();
Filter Hasil Kelompok
// Kategori yang punya lebih dari 10 post
$popularCategories = Post::select('category_id')
->selectRaw('count(*) as posts_count')
->groupBy('category_id')
->having('posts_count', '>', 10)
->get();
Query Bersyarat dengan when()
Method when()
berguna banget buat bikin query yang dinamis. Jadi bisa berubah tergantung kondisi.
Query Sederhana dengan Kondisi
$posts = Post::query()
->when(request('search'), function ($query, $search) {
$query->where('title', 'like', '%' . $search . '%');
})
->when(request('category'), function ($query, $category) {
$query->where('category_id', $category);
})
->get();
Beberapa Kondisi Sekaligus
$users = User::query()
->when(request('role'), function ($query, $role) {
$query->where('role', $role);
})
->when(request('active_only'), function ($query) {
$query->where('status', 'active');
})
->get();
Kondisi dengan Pilihan
$posts = Post::query()
->when(auth()->user()->role == 'admin',
function ($query) {
// Admin bisa lihat semua
return $query;
},
function ($query) {
// User biasa cuma lihat punya sendiri
return $query->where('user_id', auth()->id());
}
)
->get();
Query Relasi yang Mudah Dipahami
Query relasi itu buat ngambil data yang punya hubungan dengan tabel lain.
Cari Data yang Punya Relasi
// Post yang punya komentar
$postsWithComments = Post::has('comments')->get();
// Post yang punya lebih dari 5 komentar
$popularPosts = Post::has('comments', '>', 5)->get();
// Post yang dikomentar user tertentu
$posts = Post::whereHas('comments', function ($query) {
$query->where('user_id', 1);
})->get();
Hitung Jumlah Relasi
// Ambil post beserta jumlah komentarnya
$posts = Post::withCount('comments')->get();
// Hitung beberapa relasi sekaligus
$posts = Post::withCount(['comments', 'likes'])->get();
// Hitung komentar terbaru (7 hari terakhir)
$posts = Post::withCount([
'comments as recent_comments_count' => function ($query) {
$query->where('created_at', '>', now()->subDays(7));
}
])->get();
Cek Apakah Data Ada
// Cek apakah user punya post
$hasPost = Post::where('user_id', 1)->exists();
// Lebih cepat daripada count() > 0
if (User::where('email', $email)->exists()) {
echo "Email udah ada";
}
Filter Berdasarkan Relasi
// User yang punya post dalam 30 hari terakhir
$activeUsers = User::whereHas('posts', function ($query) {
$query->where('created_at', '>', now()->subDays(30));
})->get();
Raw Query untuk Kasus Khusus
Kadang butuh query mentah SQL buat hal-hal yang kompleks.
Hitung dengan Rumus
// Hitung engagement score
$posts = Post::selectRaw('*, (view_count + comment_count * 2) as engagement_score')
->orderBy('engagement_score', 'desc')
->get();
// Format tanggal
$sales = Sale::selectRaw('DATE(created_at) as sale_date')
->selectRaw('SUM(amount) as total')
->groupBy('sale_date')
->get();
Kondisi Kompleks
// Cari berdasarkan rentang hari
$posts = Post::whereRaw('DATEDIFF(NOW(), created_at) BETWEEN ? AND ?', [7, 30])
->get();
Update dengan Perhitungan
// Tambah view count
Post::where('id', 1)->update([
'view_count' => DB::raw('view_count + 1')
]);
Pagination - Bagi Data Jadi Halaman
Pagination berguna buat bagi data jadi beberapa halaman, jadi gak loading semua sekaligus.
Pagination Dasar
// Pagination biasa
$posts = Post::paginate(15);
// Pagination sederhana (cuma Next/Previous)
$posts = Post::simplePaginate(15);
// Jumlah per halaman dari request
$perPage = request('per_page', 15);
$posts = Post::paginate($perPage);
Pagination dengan Filter
$posts = Post::where('status', 'published')
->when(request('search'), function ($query, $search) {
$query->where('title', 'like', '%' . $search . '%');
})
->orderBy('created_at', 'desc')
->paginate(10);
Subquery - Query di Dalam Query
Subquery berguna buat ambil data yang lebih kompleks dalam satu kali jalan.
Ambil Data Tambahan
// Ambil user dengan judul post terbarunya
$users = User::addSelect([
'latest_post_title' => Post::select('title')
->whereColumn('user_id', 'users.id')
->orderBy('created_at', 'desc')
->limit(1)
])->get();
Filter dengan Subquery
// User yang punya post dengan views > 100
$users = User::whereIn('id', function ($query) {
$query->select('user_id')
->from('posts')
->where('view_count', '>', 100);
})->get();
Cek Keberadaan dengan Subquery
// Post yang belum ada komentarnya
$posts = Post::whereNotExists(function ($query) {
$query->select(DB::raw(1))
->from('comments')
->whereColumn('posts.id', 'comments.post_id');
})->get();
Operasi Banyak Data Sekaligus
Kalau mau insert, update, atau delete banyak data, lebih baik sekaligus daripada satu-satu.
Insert Banyak Data
$posts = [];
for ($i = 0; $i < 100; $i++) {
$posts[] = [
'title' => 'Post ' . $i,
'content' => 'Isi post ' . $i,
'user_id' => 1,
'created_at' => now(),
'updated_at' => now(),
];
}
// Insert semua sekaligus - lebih cepat
Post::insert($posts);
Delete Banyak Data
// Delete berdasarkan array ID
Post::whereIn('id', [1, 2, 3, 4, 5])->delete();
// Soft delete banyak data
Post::whereIn('id', $postIds)->update(['deleted_at' => now()]);
Insert atau Update
$data = [
['email' => 'john@example.com', 'name' => 'John'],
['email' => 'jane@example.com', 'name' => 'Jane'],
];
// Kalau email udah ada, update name. Kalau belum, insert baru
User::upsert($data, 'email', ['name']);
Database Transaction - Jaga Konsistensi Data
Transaction berguna buat pastikan kalau ada beberapa operasi database yang harus sukses semua atau gagal semua.
Transaction Sederhana
DB::transaction(function () {
// Buat user baru
$user = User::create([
'name' => 'John Doe',
'email' => 'john@example.com',
]);
// Buat profile untuk user tersebut
Profile::create([
'user_id' => $user->id,
'bio' => 'Laravel developer',
]);
// Kalau ada error di manapun, semua dibatalkan
});
Transaction Manual
DB::beginTransaction();
try {
$order = Order::create($orderData);
foreach ($items as $item) {
OrderItem::create([
'order_id' => $order->id,
'product_id' => $item['product_id'],
'quantity' => $item['quantity'],
]);
// Kurangi stok
Product::where('id', $item['product_id'])
->decrement('stock', $item['quantity']);
}
DB::commit(); // Simpan semua perubahan
} catch (Exception $e) {
DB::rollback(); // Batalkan semua perubahan
throw $e;
}
Transaction yang Return Value
$order = DB::transaction(function () {
$order = Order::create($orderData);
$this->processPayment($order);
$this->sendEmail($order);
return $order; // Bisa return value dari transaction
});
Nah, itu dia 10 query Laravel yang wajib dikuasai! Dengan menguasai query-query ini, kamu bisa bikin aplikasi Laravel yang lebih cepat dan efisien.
Yang penting diingat:
- Selalu gunakan eager loading buat hindari N+1 problem
- Pakai scope buat query yang sering diulang
- Manfaatkan pagination buat data yang banyak
- Gunakan transaction buat operasi yang butuh konsistensi
Selamat coding dengan Laravel!