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())
RetornostdClass o colecciones simplesModelos Eloquent con relaciones, casts, etc.
RelacionesManual (joins)Automático (with(), has())
Eventos / mutadoresNo
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());