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.
Pots provar les teves consultes SQL directament al navegador amb el Playground de MySQL, o demanar ajuda a l'agent d'IA per a SQL de Tutorial MySQL.