LARAVEL QUERY BUILDER
Laravel Query Builder es la interfaz fluida y orientada a objetos que Laravel ofrece para construir consultas SQL de forma segura y expresiva, sin necesidad de escribir SQL crudo en la mayoría de los casos. Está disponible a través de la facade DB y es la base sobre la que se construye Eloquent ORM (aunque Eloquent añade más abstracción con modelos).Funciona con todos los drivers soportados: MySQL, PostgreSQL, SQLite, SQL Server, etc... y es ideal para consultas dinámicas, reportes complejos, o cuando no quieres/ necesitas un modelo Eloquent.
Diferencias rápidas entre Query Builder y Eloquent
| Aspecto | Query Builder (DB::table()) | Eloquent (User::query()) |
|---|---|---|
| Retorno | stdClass o colecciones simples | Modelos Eloquent con relaciones, casts, etc. |
| Relaciones | Manual (joins) | Automático (with(), has()) |
| Eventos / mutadores | No | Sí |
| Mejor para | Reportes raw, migraciones, seeds | CRUD de modelos con lógica de negocio |
| Performance | Ligeramente más rápido (menos overhead) | Muy cercano en Laravel moderno |
Ejemplos
- Consulta básica – Obtener todos los usuarios
use Illuminate\Support\Facades\DB;
$users = DB::table('users')->get();
// Acceder como objetos stdClass
foreach ($users as $user) {
echo $user->name . ' (' . $user->email . ')' . PHP_EOL;
}
- Condiciones where (básicas y avanzadas)
// Simple
$activeUsers = DB::table('users')
->where('active', true)
->where('created_at', '>', now()->subMonth())
->get();
// Múltiples condiciones con OR
$users = DB::table('users')
->where('role', 'admin')
->orWhere(function ($query) {
$query->where('role', 'editor')
->where('verified', true);
})
->get();
// Nuevo en versiones recientes: nestedWhere() (mejora legibilidad en Laravel 12+)
$complex = DB::table('users')
->nestedWhere(function ($query) {
$query->where('active', true)
->orWhere('trial_ends', '>', now())
->where('visits', '>', 10);
})
->get();
- Select específico, orderBy, limit, offset
$topUsers = DB::table('users')
->select('id', 'name', 'points')
->where('points', '>', 1000)
->orderByDesc('points')
->limit(10)
->offset(20) // página 3 si paginamos de 10 en 10
->get();
- Joins (inner, left, right, cross)
$ordersWithUser = DB::table('orders')
->join('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', 'users.name as customer_name')
->where('orders.status', 'completed')
->get();
// Left join + condición extra
$products = DB::table('products')
->leftJoin('reviews', function ($join) {
$join->on('products.id', '=', 'reviews.product_id')
->where('reviews.rating', '>=', 4);
})
->select('products.*', DB::raw('AVG(reviews.rating) as avg_rating'))
->groupBy('products.id')
->get();
- Agregados y raw expressions
// Conteo simple
$totalUsers = DB::table('users')->count();
// Múltiples agregados
$stats = DB::table('orders')
->selectRaw('COUNT(*) as total_orders')
->selectRaw('SUM(total) as total_revenue')
->selectRaw('AVG(total) as avg_order')
->first();
// Raw con binding (seguro)
$expensive = DB::table('products')
->whereRaw('price > ? AND stock > 0', [1000])
->get();
- Inserts, updates, deletes
// Insert simple
DB::table('users')->insert([
'name' => 'Ana López',
'email' => 'ana@example.com',
'created_at' => now(),
]);
// Insert múltiple
DB::table('tags')->insert([
['name' => 'laravel', 'slug' => 'laravel'],
['name' => 'php', 'slug' => 'php'],
]);
// Update con condición
DB::table('users')
->where('id', 1)
->update(['active' => false, 'updated_at' => now()]);
// Increment / decrement
DB::table('posts')->where('id', 5)->increment('views', 1);
// Delete
DB::table('comments')->where('post_id', 10)->delete();
- Paginación manual (sin Eloquent)
$perPage = 15;
$page = request()->input('page', 1);
$users = DB::table('users')
->orderBy('created_at', 'desc')
->paginate($perPage, ['*'], 'page', $page);
- Debugging – Ver la consulta generada
$query = DB::table('users')->where('active', 1);
// Opción 1: toSql() + getBindings()
dd($query->toSql(), $query->getBindings());
// Opción 2: enableQueryLog() (muy útil en desarrollo)
DB::enableQueryLog();
$results = $query->get();
dd(DB::getQueryLog());
- Debugging – Ver la consulta generada
$query = DB::table('users')->where('active', 1);
// Opción 1: toSql() + getBindings()
dd($query->toSql(), $query->getBindings());
// Opción 2: enableQueryLog() (muy útil en desarrollo)
DB::enableQueryLog();
$results = $query->get();
dd(DB::getQueryLog());
use Illuminate\Support\Facades\DB;
$users = DB::table('users')->get();
// Acceder como objetos stdClass
foreach ($users as $user) {
echo $user->name . ' (' . $user->email . ')' . PHP_EOL;
}
// Simple
$activeUsers = DB::table('users')
->where('active', true)
->where('created_at', '>', now()->subMonth())
->get();
// Múltiples condiciones con OR
$users = DB::table('users')
->where('role', 'admin')
->orWhere(function ($query) {
$query->where('role', 'editor')
->where('verified', true);
})
->get();
// Nuevo en versiones recientes: nestedWhere() (mejora legibilidad en Laravel 12+)
$complex = DB::table('users')
->nestedWhere(function ($query) {
$query->where('active', true)
->orWhere('trial_ends', '>', now())
->where('visits', '>', 10);
})
->get();
$topUsers = DB::table('users')
->select('id', 'name', 'points')
->where('points', '>', 1000)
->orderByDesc('points')
->limit(10)
->offset(20) // página 3 si paginamos de 10 en 10
->get();
$ordersWithUser = DB::table('orders')
->join('users', 'orders.user_id', '=', 'users.id')
->select('orders.*', 'users.name as customer_name')
->where('orders.status', 'completed')
->get();
// Left join + condición extra
$products = DB::table('products')
->leftJoin('reviews', function ($join) {
$join->on('products.id', '=', 'reviews.product_id')
->where('reviews.rating', '>=', 4);
})
->select('products.*', DB::raw('AVG(reviews.rating) as avg_rating'))
->groupBy('products.id')
->get();
// Conteo simple
$totalUsers = DB::table('users')->count();
// Múltiples agregados
$stats = DB::table('orders')
->selectRaw('COUNT(*) as total_orders')
->selectRaw('SUM(total) as total_revenue')
->selectRaw('AVG(total) as avg_order')
->first();
// Raw con binding (seguro)
$expensive = DB::table('products')
->whereRaw('price > ? AND stock > 0', [1000])
->get();
// Insert simple
DB::table('users')->insert([
'name' => 'Ana López',
'email' => 'ana@example.com',
'created_at' => now(),
]);
// Insert múltiple
DB::table('tags')->insert([
['name' => 'laravel', 'slug' => 'laravel'],
['name' => 'php', 'slug' => 'php'],
]);
// Update con condición
DB::table('users')
->where('id', 1)
->update(['active' => false, 'updated_at' => now()]);
// Increment / decrement
DB::table('posts')->where('id', 5)->increment('views', 1);
// Delete
DB::table('comments')->where('post_id', 10)->delete();
$perPage = 15;
$page = request()->input('page', 1);
$users = DB::table('users')
->orderBy('created_at', 'desc')
->paginate($perPage, ['*'], 'page', $page);
$query = DB::table('users')->where('active', 1);
// Opción 1: toSql() + getBindings()
dd($query->toSql(), $query->getBindings());
// Opción 2: enableQueryLog() (muy útil en desarrollo)
DB::enableQueryLog();
$results = $query->get();
dd(DB::getQueryLog());
$query = DB::table('users')->where('active', 1);
// Opción 1: toSql() + getBindings()
dd($query->toSql(), $query->getBindings());
// Opción 2: enableQueryLog() (muy útil en desarrollo)
DB::enableQueryLog();
$results = $query->get();
dd(DB::getQueryLog());