LARAVEL QUERY BUILDER: CÓMO CONSTRUIR CONSULTAS

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())
RetornostdClass o colecciones simplesModelos Eloquent con relaciones, casts, etc.
RelacionesManual (joins)Automático (with(), has())
Eventos / mutadoresNoSí
Mejor paraReportes raw, migraciones, seedsCRUD de modelos con lógica de negocio
PerformanceLigeramente 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());