Laravel Query Builder Reference Guide

A reference guide to Laravel's fluent query builder for reading and writing data without raw SQL.

Getting started

The DB facade gives you a fluent interface for building and running queries against any configured database connection, without writing raw SQL by hand. Every method returns the query builder itself (except the terminal methods like get()), so calls chain together.

use Illuminate\Support\Facades\DB;

$users = DB::table('users')->get();

$user = DB::table('users')->where('id', 1)->first();

$name = DB::table('users')->where('id', 1)->value('name');

$exists = DB::table('users')->where('email', $email)->exists();

Select clauses

DB::table('users')->select('id', 'name', 'email')->get();

DB::table('users')->select('name as full_name')->get();

DB::table('users')->distinct()->pluck('country');

Where clauses

The most common way to filter results. Chain multiple where() calls to combine them with AND; use orWhere() for OR.

DB::table('users')
    ->where('active', true)
    ->where('age', '>=', 18)
    ->orWhere('role', 'admin')
    ->get();

DB::table('users')->whereIn('id', [1, 2, 3])->get();
DB::table('users')->whereNotIn('id', [1, 2, 3])->get();
DB::table('users')->whereBetween('age', [18, 30])->get();
DB::table('users')->whereNull('deleted_at')->get();
DB::table('users')->whereNotNull('email_verified_at')->get();
DB::table('posts')->whereDate('created_at', '2026-01-01')->get();

// Group conditions with a closure to control operator precedence
DB::table('users')->where(function ($query) {
    $query->where('role', 'admin')
          ->orWhere('role', 'manager');
})->where('active', true)->get();

Ordering, grouping, and limiting

DB::table('users')->orderBy('name')->get();
DB::table('users')->orderByDesc('created_at')->get();
DB::table('users')->latest()->first();   // orderBy('created_at', 'desc')
DB::table('users')->oldest()->first();

DB::table('orders')
    ->select('customer_id', DB::raw('SUM(total) as total_spent'))
    ->groupBy('customer_id')
    ->having('total_spent', '>', 1000)
    ->get();

DB::table('users')->skip(10)->take(5)->get();
DB::table('users')->paginate(15);

Joins

DB::table('users')
    ->join('orders', 'users.id', '=', 'orders.user_id')
    ->select('users.name', 'orders.total')
    ->get();

DB::table('users')
    ->leftJoin('orders', 'users.id', '=', 'orders.user_id')
    ->get();

Aggregates

DB::table('orders')->count();
DB::table('orders')->max('total');
DB::table('orders')->min('total');
DB::table('orders')->avg('total');
DB::table('orders')->sum('total');

Inserts, updates, and deletes

DB::table('users')->insert([
    'name' => 'Jane Doe',
    'email' => 'jane@example.com',
]);

$id = DB::table('users')->insertGetId([
    'name' => 'Jane Doe',
]);

DB::table('users')->where('id', 1)->update(['votes' => 1]);

DB::table('users')->where('votes', '<', 100)->increment('votes', 5);

DB::table('users')->where('id', 1)->delete();

Raw expressions

Drop down to raw SQL fragments when the fluent methods don't cover what you need — but prefer bindings (? placeholders) over string-interpolating user input to avoid SQL injection.

DB::select('select * from users where active = ?', [true]);

DB::table('users')
    ->whereRaw('age > ? and active = ?', [18, true])
    ->get();