LaravelEloquentQueryMenengah4 mnt baca

Eloquent Read: Query yang Ekspresif

Mengambil data: find, where, orderBy, dan paginasi dasar.

Kenapa Query yang Ekspresif Penting?

Hampir setiap halaman aplikasi membaca data dari database. Query yang ekspresif artinya kamu cukup bilang "apa" yang kamu mau, bukan "bagaimana" cara mengambilnya. Laravel menerjemahkannya menjadi SQL yang efisien, dan kode yang kamu tulis tetap terbaca seperti kalimat biasa. Ini alasan Eloquent terasa menyenangkan dipakai.

Mengambil Satu Baris

php
// app/Http/Controllers/PostController.php
$post = Post::find(1);                       // null kalau tidak ada
$post = Post::findOrFail(1);                 // otomatis 404 kalau tidak ada
$post = Post::firstWhere('slug', 'hello');   // where + first dalam satu panggil

findOrFail() adalah favorit untuk halaman detail: kalau id tidak ada, Laravel melempar ModelNotFoundException yang otomatis diubah menjadi halaman 404. Tidak perlu if manual lagi.

Jebakan umum: memakai find() lalu langsung mengakses $post->title tanpa mengecek null. Kalau datanya tidak ada, kamu mendapat error "Attempt to read property on null". Aturannya sederhana: find() selalu dipasangkan dengan pengecekan, atau pakai findOrFail() sekalian.

Mengambil Banyak dengan Method Chain

php
// app/Http/Controllers/PostController.php
$posts = Post::where('published_at', '<=', now())
    ->where('views', '>', 100)
    ->orderBy('published_at', 'desc')
    ->limit(10)
    ->get();

Setiap method mengembalikan query builder yang sama, jadi bisa dirangkai. Tidak ada query yang berjalan sampai kamu memanggil get(), first(), atau paginate(). Ini disebut deferred execution: Laravel menunda eksekusi sampai hasilnya benar-benar diminta, sehingga kamu bebas menyusun kondisi dulu.

Kondisional Dinamis dari Request

Filter opsional dari request adalah kasus klasik. Jangan tulis if-else dengan dua query terpisah, bangun satu builder saja:

php
// app/Http/Controllers/PostController.php
$query = Post::query();

if ($request->filled('kategori')) {
    $query->where('category_id', $request->kategori);
}

if ($request->filled('q')) {
    $query->where('title', 'like', '%' . $request->q . '%');
}

$posts = $query->latest()->paginate(10);

Post::query() memberi builder kosong yang siap di-chain. latest() adalah shortcut untuk orderBy('created_at', 'desc'). paginate() otomatis membaca ?page= dari URL, memotong data per halaman, dan menyediakan link halaman yang siap dipakai di Blade.

Jebakan umum: memakai $request->kategori langsung di where tanpa filled(). Kalau parameternya tidak ada, where('category_id', null) diterjemahkan jadi IS NULL dan hasilnya kosong misterius. filled() memastikan parameter ada dan tidak kosong sebelum dipakai sebagai filter.

Catatan teknis: get() mengembalikan Collection, array super dengan method map(), filter(), pluck(), groupBy(), dan puluhan lainnya. first() mengembalikan satu model atau null. Jangan panggil get() dua kali pada builder yang sama tanpa clone karena kondisi where akan menumpuk dan hasilnya makin sempit tanpa kamu sadari. Kalau butuh dua hasil dari kondisi dasar yang sama, clone dulu: $a = (clone $query)->get(); $b = (clone $query)->where('x', 1)->get();

Melihat SQL di Balik Query

Saat query tidak mengembalikan hasil yang kamu harapkan, intip SQL-nya langsung:

php
// app/Http/Controllers/PostController.php
$query = Post::where('views', '>', 100)->orderBy('views', 'desc');

dd($query->toSql());
// "select * from `posts` where `views` > ? order by `views` desc"

toSql() menampilkan query dengan placeholder ?. Untuk melihat lengkap beserta binding dan waktunya, aktifkan query log:

php
use Illuminate\Support\Facades\DB;

DB::enableQueryLog();
$posts = Post::with('user')->get();
dd(DB::getQueryLog()); // daftar query + binding + waktu eksekusi

Ini cara tercepat membuktikan eager loading bekerja: kode yang lazy menampilkan puluhan query identik, kode yang eager hanya dua. Biasakan mengecek query log setiap kali halaman terasa lambat sebelum menyalahkan server.

Tantangan

Query Filter

Via tinker: ambil 5 post dengan views terbanyak yang sudah published. Tulis query-nya dalam satu baris method chain.