Query Builder: Query Tanpa Model
Tulis query kompleks dengan DB::table: join, agregat, dan chunking untuk data besar.
Kapan pakai query builder?
Eloquent enak untuk CRUD per baris, tapi untuk laporan, agregat, atau join kompleks, query builder (DB::table) lebih ringan karena tidak membuat object model:
use Illuminate\Support\Facades\DB;
$posts = DB::table('posts')
->select('status', DB::raw('COUNT(*) as total'))
->where('created_at', '>=', now()->subDays(30))
->groupBy('status')
->having('total', '>', 5)
->orderByDesc('total')
->get();Semua input otomatis di-binding sebagai parameter, jadi aman dari SQL injection tanpa perlu mikir.
Join antar tabel
$posts = DB::table('posts')
->join('users', 'posts.user_id', '=', 'users.id')
->join('kategoris', 'posts.kategori_id', '=', 'kategoris.id')
->select('posts.judul', 'users.nama as penulis', 'kategoris.nama as kategori')
->where('posts.status', 'published')
->get();
foreach ($posts as $post) {
echo $post->judul.' oleh '.$post->penulis;
}Ada juga leftJoin, crossJoin, dan subquery join untuk kasus advance.
Kondisional dinamis dengan when()
Filter pencarian yang opsional jadi rapi tanpa if bertumpuk:
$posts = DB::table('posts')
->when($request->filled('q'), function ($query) use ($request) {
$query->where('judul', 'like', '%'.$request->q.'%');
})
->when($request->filled('status'), function ($query) use ($request) {
$query->where('status', $request->status);
})
->paginate(15);Chunking: aman untuk data jutaan baris
Jangan pernah ->get() tabel dengan jutaan baris sekaligus, memory bisa jebol. Proses per batch:
DB::table('posts')->orderBy('id')->chunk(1000, function ($posts) {
foreach ($posts as $post) {
// proses 1000 baris per iterasi
}
});Catatan teknis: Query builder mengembalikan
stdClass, bukan model, jadi tidak ada relasi, accessor, atau event. Kalau butuh fitur model, tetap pakai Eloquent. Aturan praktis: Eloquent untuk logika domain, query builder untuk laporan dan agregat berat.