laraveleloquentperformaMenengah3 mnt baca

Eager Loading: Solusi N+1 Query

Pahami masalah N+1 query yang bikin halaman lambat dan atasi dengan with() dan withCount().

Masalah N+1 query

Ini jebakan performa nomor satu di Laravel. Perhatikan kode ini:

blade
@foreach ($posts as $post)
    <p>{{ $post->judul }} oleh {{ $post->user->nama }}</p>
@endforeach

Kelihatannya 1 loop biasa, tapi di belakang layar terjadi 1 query untuk ambil semua post + N query untuk ambil user tiap post. Kalau ada 100 post, total 101 query. Di development tidak terasa, di production dengan data besar halamannya jadi lambat.

Solusi: with()

Beri tahu Laravel di awal relasi apa saja yang dibutuhkan, supaya diambil dalam 1-2 query saja:

php
// app/Http/Controllers/PostController.php
public function index()
{
    // 2 query total, tidak peduli ada 10 atau 1000 post
    $posts = Post::with('user')->latest()->paginate(15);

    return view('posts.index', compact('posts'));
}

Bisa juga nested dan multiple:

php
$posts = Post::with(['user', 'komentar.user', 'tags'])->get();

Lazy eager loading

Kalau model sudah terlanjur diambil tanpa with(), load relasinya belakangan:

php
$posts = Post::all();

// Satu query tambahan untuk semua user, bukan N query
$posts->load('user');
$posts->loadMissing('tags'); // hanya yang belum di-load

withCount: hitung tanpa ambil data

Butuh jumlah komentar tiap post tanpa me-load semua komentar? Pakai withCount():

php
$posts = Post::withCount(['komentar', 'komentar as komentar_published_count' => function ($q) {
    $q->where('status', 'published');
}])->get();

foreach ($posts as $post) {
    echo $post->komentar_count; // kolom virtual otomatis
}

Catatan teknis: Cara termudah mendeteksi N+1 adalah menyalakan query log saat development: DB::enableQueryLog() lalu dd(DB::getQueryLog()). Atau install Laravel Debugbar yang menampilkan jumlah query tiap halaman. Kalau satu halaman menjalankan ratusan query, hampir pasti ada N+1 yang belum di-eager-load.