Membaca data adalah operasi yang paling sering dilakukan aplikasi, dan Eloquent menyediakan spektrum method yang membentang dari “ambil semuanya” sampai “cukup bilang ada atau tidak”. Memilih method yang tepat bukan sekadar gaya penulisan, karena method yang berbeda mengirim query berbeda ke database. Pada chapter ini kita menyusuri method retrieval satu per satu: all(), find(), first(), rantai where(), pengurutan, sampai exists() dan chunk(). Semua contoh dijalankan atas tabel posts berisi data uji yang tetap, sehingga setiap output bisa Anda cocokkan sendiri.

Data Uji: Lima Post dari Budi dan Siti #

Seluruh contoh chapter ini memakai lima baris yang sama milik dua user tetap, Budi dan Siti:

idpenulisjudulviewshargapublished
1BudiBelajar Eloquent120150000true
2BudiRahasia Query Builder45NULLfalse
3SitiMigrasi Tanpa Drama280250000true
4SitiTips Seeding Data8NULLfalse
5SitiOptimasi Query Laravel27599000true

Distribusinya sengaja dibuat tidak rata. Jumlah post, nilai views, harga, dan status publish yang bervariasi membuat dampak tiap method langsung terlihat pada hasil.

Semua Baris: all() dan Collection #

Method all() mengambil seluruh baris tabel dalam satu query:

php
use App\Models\Post;

$posts = Post::all();

echo 'all() -> ', get_class($posts), ' dengan ', $posts->count(), " baris\n";
foreach ($posts as $post) {
    echo '  ', $post->id, '. ', $post->judul, ' (views ', $post->views, ")\n";
}

Output yang Dihasilkan:

text
all() -> Illuminate\Database\Eloquent\Collection dengan 5 baris
  1. Belajar Eloquent (views 120)
  2. Rahasia Query Builder (views 45)
  3. Migrasi Tanpa Drama (views 280)
  4. Tips Seeding Data (views 8)
  5. Optimasi Query Laravel (views 275)

Hasil all() bukan array biasa, melainkan Illuminate\Database\Eloquent\Collection — wadah object yang mewarisi seluruh method Collection seperti pluck(), filter(), dan count() yang kita pakai pada contoh di atas. Bedanya dengan get() tipis: Post::get() juga mengembalikan Collection, tetapi bisa dirantai where() lebih dulu, sedangkan all() selalu mengambil tabel apa adanya. Karena selalu memuat seluruh baris ke memori, all() pantas dihindari pada tabel besar — alternatifnya chunk() di akhir chapter.

Berdasarkan Primary Key: find() dan findMany() #

Method find() mencari satu baris lewat primary key yang dibahas di chapter Membuat Model :

php
echo 'find(3) -> ', Post::find(3)->judul, "\n";
echo 'findMany([1, 3, 5]) -> ', Post::findMany([1, 3, 5])->pluck('judul')->implode(' | '), "\n";

Output yang Dihasilkan:

text
find(3) -> Migrasi Tanpa Drama
findMany([1, 3, 5]) -> Belajar Eloquent | Migrasi Tanpa Drama | Optimasi Query Laravel

findMany() menerima array primary key dan mengembalikan Collection berisi baris yang ditemukan. Keduanya adalah pintas yang jujur: find(3) setara where('id', 3)->first(), hanya jauh lebih ringkas karena pencarian lewat kunci memang kasus paling umum.

Satu Baris Pertama: first() dan firstWhere() #

Method first() menghentikan query pada baris pertama yang cocok dan menambahkan LIMIT 1 pada SQL-nya. Versi satu kondisinya bernama firstWhere():

php
echo 'first (views terendah) -> ', Post::orderBy('views')->first()->judul, "\n";

$publik = Post::where('published', true)->first();
echo 'first (published) -> ', $publik->judul, "\n";

echo 'firstWhere(slug) -> ', Post::firstWhere('slug', 'migrasi-tanpa-drama')->judul, "\n";

Output yang Dihasilkan:

text
first (views terendah) -> Tips Seeding Data
first (published) -> Belajar Eloquent
firstWhere(slug) -> Migrasi Tanpa Drama

first() mengikuti urutan hasil query: dengan orderBy('views') ia mengambil post ber-views terkecil, dan tanpa orderBy ia mengikuti urutan alami tabel sehingga post pertama Budi yang menang. Method firstWhere('slug', ...) hanyalah kependekan where('slug', ...)->first() untuk pencarian satu kondisi.

Menyaring dengan where() dan Teman-temannya #

Rantai where() bekerja persis seperti di Query Builder dan bisa disambung terus sebelum diakhiri get(). Berikut keluarga penyaring yang paling sering terpakai dalam satu kesatuan:

php
$hasil = Post::where('user_id', 1)->orWhere('views', '>', 250)->orderBy('id')->get();
echo 'user_id=1 OR views>250 -> ', $hasil->pluck('judul')->implode(' | '), "\n";

echo 'whereIn(user_id, [1]) -> ', Post::whereIn('user_id', [1])->count(), " post milik Budi\n";
echo 'whereNotIn(user_id, [1]) -> ', Post::whereNotIn('user_id', [1])->count(), " post milik Siti\n";

$menengah = Post::whereBetween('views', [100, 300])->orderBy('views')->get();
echo 'views 100..300 -> ', $menengah->pluck('judul')->implode(' | '), "\n";

echo 'harga NULL -> ', Post::whereNull('harga')->pluck('slug')->implode(', '), "\n";

Output yang Dihasilkan:

text
user_id=1 OR views>250 -> Belajar Eloquent | Rahasia Query Builder | Migrasi Tanpa Drama | Optimasi Query Laravel
whereIn(user_id, [1]) -> 2 post milik Budi
whereNotIn(user_id, [1]) -> 3 post milik Siti
views 100..300 -> Belajar Eloquent | Optimasi Query Laravel | Migrasi Tanpa Drama
harga NULL -> rahasia-query-builder, tips-seeding-data

Mari kita baca hasilnya baris demi baris. orWhere() melebarkan kondisi: dua post Budi lolos karena user_id = 1, lalu dua post Siti menyusul karena views-nya di atas 250. whereIn() membatasi hasil pada sekumpulan nilai dan whereNotIn() membaliknya, sedangkan whereBetween('views', [100, 300]) menjaring rentang inklusif antara 100 dan 300. Terakhir, whereNull() menemukan baris yang kolomnya memang NULL — sesuatu yang tidak bisa dijawab where('harga', null) karena perbandingan = NULL di SQL tidak pernah benar.

Urutan: orderBy, latest, dan oldest() #

Pengurutan menentukan baris mana yang tampil lebih dulu, dan Eloquent menyediakan dua pintasan yang sangat praktis:

php
echo 'orderByDesc(views) -> ', Post::orderByDesc('views')->pluck('judul')->implode(' | '), "\n";
echo 'latest() -> ', Post::latest()->first()->judul, "\n";
echo 'oldest() -> ', Post::oldest()->first()->judul, "\n";

Output yang Dihasilkan:

text
orderByDesc(views) -> Migrasi Tanpa Drama | Optimasi Query Laravel | Belajar Eloquent | Rahasia Query Builder | Tips Seeding Data
latest() -> Optimasi Query Laravel
oldest() -> Belajar Eloquent

latest() dan oldest() adalah kependekan dari orderBy('created_at', 'desc') dan orderBy('created_at', 'asc'). Post id 5 adalah yang paling akhir dibuat sehingga latest() menjemputnya, sementara post id 1 paling tua sehingga menjadi hasil oldest(). Kedua method ini juga menerima nama kolom lain, misalnya latest('updated_at').

Kolom Tunggal: value() dan pluck() #

Kadang kita hanya butuh satu nilai, bukan object utuh. Method value() mengambil satu kolom dari baris pertama hasil query, sedangkan pluck() mengambil satu kolom dari semua baris:

php
echo "value('judul') -> ", Post::orderByDesc('views')->value('judul'), "\n";

echo 'pluck Budi -> ', Post::where('user_id', 1)->orderBy('id')->pluck('judul')->implode(' | '), "\n";

Output yang Dihasilkan:

text
value('judul') -> Migrasi Tanpa Drama
pluck Budi -> Belajar Eloquent | Rahasia Query Builder

value() menghemat transfer data karena SQL-nya hanya memilih satu kolom, dan pluck() mengembalikan Collection datar yang siap dipakai untuk mengisi dropdown atau mengecek keanggotaan. Method pluck() juga bisa menerima kolom kedua sebagai kunci hasil, misalnya pluck('judul', 'id') yang menghasilkan pasangan id-judul.

exists(), count(), dan chunk() #

Tiga penutup chapter ini bahkan tidak mengembalikan model sama sekali. Method exists() menjawab “ada atau tidak” lewat query sehemat SELECT EXISTS, count() menghitung baris di sisi database tanpa memuatnya, dan chunk() memproses tabel besar per potongan:

php
echo 'exists(slug belajar-eloquent) -> ', Post::where('slug', 'belajar-eloquent')->exists() ? 'true' : 'false', "\n";
echo 'exists(views > 300) -> ', Post::where('views', '>', 300)->exists() ? 'true' : 'false', "\n";
echo 'count published -> ', Post::where('published', true)->count(), "\n";

$kantong = [];
Post::orderBy('id')->chunk(2, function ($bagian) use (&$kantong) {
    $kantong[] = $bagian->pluck('id')->implode(',');
});
echo 'chunk(2) -> ', implode(' / ', $kantong), "\n";

Output yang Dihasilkan:

text
exists(slug belajar-eloquent) -> true
exists(views > 300) -> false
count published -> 3
chunk(2) -> 1,2 / 3,4 / 5

Baris pertama membuktikan slug itu ada dan baris kedua membuktikan tidak ada post dengan views di atas 300. count() menghitung tiga post yang published tanpa memuat satu pun ke memori. Terakhir, chunk(2, ...) mengeksekusi query berulang kali — callback dipanggil tiga kali dengan Collection berisi dua, dua, lalu satu model — sehingga memori tetap rata berapa pun ukuran tabel. Satu syarat penting: selalu sertakan orderBy pada kolom unik agar setiap potongan tidak menampilkan baris yang sama dua kali.

Membaca data menjadi mudah begitu method yang tersedia dikenali satu per satu. Namun semua contoh di atas hanya membaca — tabel belum bertambah satu baris pun. Chapter berikutnya mengisi sisi itu: create(), firstOrCreate, updateOrCreate, dan teman-temannya untuk menyimpan data baru.