Query Builder
Com fer consultes amb el Query Builder de Laravel: selects, wheres, joins i agregats.
Què és el Query Builder?#
El Query Builder de Laravel permet construir consultes SQL de manera fluida i expressiva sense escriure SQL directament. Genera consultes segures amb prepared statements, protegint contra injeccions SQL. A diferència d'Eloquent (que treballa amb models), el Query Builder opera directament amb les taules de la base de dades.
Consultes bàsiques#
Per començar una consulta, utilitza la facade DB amb el mètode table():
use Illuminate\Support\Facades\DB;
// Obtenir tots els registres d'una taula
$users = DB::table('users')->get();
// Primer registre que compleix la condició
$user = DB::table('users')->where('email', 'admin@exemple.com')->first();
// Valor d'una sola columna
$name = DB::table('users')->where('id', 1)->value('name');
// Llista de valors d'una columna
$emails = DB::table('users')->pluck('email');
// Llista clau-valor (útil per a selects de formularis)
$users = DB::table('users')->pluck('name', 'id');
// [1 => 'Joan', 2 => 'Maria', 3 => 'Pere']El mètode get() retorna una col·lecció amb tots els resultats. first() retorna un sol objecte o null si no troba res. value() retorna el valor d'una sola columna del primer resultat.
Si vols assegurar-te que el registre existeix i llançar una excepció 404 si no, utilitza firstOrFail():
$user = DB::table('users')->where('id', $id)->firstOrFail();Seleccionar columnes#
Per defecte, get() selecciona totes les columnes (SELECT *). Pots limitar-ho amb select():
$users = DB::table('users')
->select('name', 'email')
->get();
// Amb àlies
$users = DB::table('users')
->select('name', 'email as correu')
->get();
// Afegir una columna a la selecció
$users = DB::table('users')
->select('name')
->addSelect('email')
->get();
// Valors diferents (DISTINCT)
$cities = DB::table('users')
->distinct()
->select('city')
->get();Condicions WHERE#
El mètode where() afegeix condicions a la consulta. La forma més bàsica accepta tres paràmetres: columna, operador i valor. Quan l'operador és =, pots ometre'l:
// WHERE active = true
$users = DB::table('users')->where('active', true)->get();
// WHERE age >= 18
$users = DB::table('users')->where('age', '>=', 18)->get();
// WHERE name LIKE '%Joan%'
$users = DB::table('users')->where('name', 'like', '%Joan%')->get();Pots encadenar múltiples where() per combinar condicions amb AND:
$users = DB::table('users')
->where('active', true)
->where('age', '>=', 18)
->where('role', 'editor')
->get();Per a condicions OR, utilitza orWhere():
$users = DB::table('users')
->where('role', 'admin')
->orWhere('role', 'editor')
->get();Condicions avançades#
Laravel proporciona mètodes específics per a les condicions SQL més comunes:
// WHERE IN
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
// WHERE NOT IN
$users = DB::table('users')
->whereNotIn('status', ['banned', 'suspended'])
->get();
// WHERE BETWEEN
$users = DB::table('users')
->whereBetween('age', [18, 65])
->get();
// WHERE NULL
$unverified = DB::table('users')
->whereNull('email_verified_at')
->get();
// WHERE NOT NULL
$verified = DB::table('users')
->whereNotNull('email_verified_at')
->get();
// WHERE DATE
$todayUsers = DB::table('users')
->whereDate('created_at', today())
->get();
// WHERE columna = altra columna
$users = DB::table('users')
->whereColumn('created_at', '=', 'updated_at')
->get();Agrupació de condicions#
Per crear condicions complexes amb parèntesis, passa un closure a where():
// WHERE active = true AND (role = 'admin' OR role = 'editor')
$users = DB::table('users')
->where('active', true)
->where(function ($query) {
$query->where('role', 'admin')
->orWhere('role', 'editor');
})
->get();Ordenar i limitar#
// Ordenar per nom ascendent
$users = DB::table('users')
->orderBy('name', 'asc')
->get();
// Ordenar per múltiples columnes
$users = DB::table('users')
->orderBy('role', 'asc')
->orderBy('name', 'asc')
->get();
// Últims registres (orderBy created_at DESC)
$latest = DB::table('articles')->latest()->get();
// Primers registres (orderBy created_at ASC)
$oldest = DB::table('articles')->oldest()->get();
// Ordre aleatori
$random = DB::table('users')->inRandomOrder()->first();
// Limitar resultats
$users = DB::table('users')
->orderBy('name')
->limit(10)
->offset(20)
->get();Agregats#
Les funcions d'agregat retornen un valor únic en lloc d'una col·lecció de resultats:
$count = DB::table('users')->count();
$maxAge = DB::table('users')->max('age');
$minPrice = DB::table('products')->min('price');
$avgRating = DB::table('reviews')->avg('rating');
$totalRevenue = DB::table('orders')->where('status', 'paid')->sum('total');
// Comprovar si existeixen registres
$exists = DB::table('users')->where('email', $email)->exists();
$doesntExist = DB::table('users')->where('email', $email)->doesntExist();Joins#
Per combinar dades de múltiples taules, utilitza els mètodes de join:
// INNER JOIN
$articles = DB::table('articles')
->join('users', 'articles.user_id', '=', 'users.id')
->select('articles.*', 'users.name as author_name')
->get();
// LEFT JOIN (inclou articles sense autor)
$articles = DB::table('articles')
->leftJoin('users', 'articles.user_id', '=', 'users.id')
->select('articles.*', 'users.name as author_name')
->get();
// Join amb múltiples condicions
$articles = DB::table('articles')
->join('categories', function ($join) {
$join->on('articles.category_id', '=', 'categories.id')
->where('categories.active', true);
})
->get();Group By i Having#
Per agrupar resultats i filtrar-los:
// Comptar articles per autor
$authors = DB::table('articles')
->join('users', 'articles.user_id', '=', 'users.id')
->select('users.name', DB::raw('COUNT(*) as total_articles'))
->groupBy('users.name')
->having('total_articles', '>', 5)
->get();Inserir, actualitzar i eliminar#
El Query Builder també permet modificar dades:
// Inserir un registre
DB::table('users')->insert([
'name' => 'Joan',
'email' => 'joan@exemple.com',
'created_at' => now(),
]);
// Inserir i obtenir l'ID
$id = DB::table('users')->insertGetId([
'name' => 'Joan',
'email' => 'joan@exemple.com',
]);
// Inserir múltiples registres
DB::table('users')->insert([
['name' => 'Joan', 'email' => 'joan@ex.com'],
['name' => 'Maria', 'email' => 'maria@ex.com'],
]);
// Actualitzar registres
DB::table('users')
->where('id', 1)
->update(['name' => 'Joan Pere']);
// Incrementar o decrementar un valor
DB::table('articles')->where('id', 1)->increment('views');
DB::table('products')->where('id', 1)->decrement('stock', 5);
// Actualitzar o inserir (upsert)
DB::table('users')->updateOrInsert(
['email' => 'joan@ex.com'], // Condició de cerca
['name' => 'Joan', 'active' => true] // Valors a actualitzar/inserir
);
// Eliminar registres
DB::table('users')->where('active', false)->delete();
// Eliminar tots els registres
DB::table('logs')->truncate();Chunking per a grans volums#
Quan treballes amb milers de registres, carregar-los tots a memòria pot ser un problema. El mètode chunk() processa els resultats en grups:
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
foreach ($users as $user) {
// Processar cada usuari
}
});
// Lazy collection (encara més eficient en memòria)
DB::table('users')->orderBy('id')->lazy()->each(function ($user) {
// Processar cada usuari
});El chunk() fa una consulta per cada grup de 100 registres, mantenint el consum de memòria baix independentment del nombre total de registres.