Como criar WHERE complexo no Laravel Eloquent: 4 métodos com exemplos
\n\nImagine: você está desenvolvendo uma loja virtual em Laravel. Precisa encontrar todos os produtos que custam entre R$ 100 e R$ 500, estão em estoque, mas não pertencem à categoria "Promoção", e ainda foram criados após 1º de janeiro de 2024. Como fazer isso em uma única consulta sem prejudicar a performance?
\n\nEssa é uma das perguntas mais populares no Stack Overflow (milhares de visualizações!). E não é à toa: saber construir condições WHERE complexas no Laravel Eloquent é o que diferencia um iniciante de um desenvolvedor profissional.
\n\nNeste artigo, vou mostrar 4 métodos testados e aprovados para criar múltiplas condições WHERE. Você vai aprender quando usar arrays, quando usar closures, como agrupar condições e como evitar SQL injection. Vamos nessa!
\n\n\n\n
1. Método básico: array de condições (para AND simples)
\n\nO caso mais simples é quando todas as condições são unidas por AND. O Laravel permite passar um array comum para o where():
<?php\n\n// Queremos encontrar usuários ativos do Brasil, criados em 2024\n$users = User::where([\n ['status', '=', 'active'],\n ['country', '=', 'Brazil'],\n ['created_at', '>=', '2024-01-01'],\n])->get();\n\n// SQL: SELECT * FROM users WHERE status = 'active' AND country = 'Brazil' AND created_at >= '2024-01-01'\n\nQuando usar: quando você tem de 2 a 5 condições simples com operador = ou >. O código fica legível, mas não é flexível.
Desvantagem: se precisar misturar AND e OR, o array não funciona.
2. Encadeamento de métodos where() (para condições dinâmicas)
\n\nEste é o método mais popular entre os desenvolvedores. Basta chamar where() várias vezes em sequência:
<?php\n\n$products = Product::where('price', '>', 100)\n ->where('price', '<', 500)\n ->where('in_stock', true)\n ->where('category_id', '!=', 5)\n ->get();\n\n// SQL: ... WHERE price > 100 AND price < 500 AND in_stock = 1 AND category_id <> 5\n\nDica: você pode combinar com outras condições:
\n\n<?php\n\n// Condição "OR" dentro do encadeamento\n$orders = Order::where('status', 'paid')\n ->orWhere('status', 'shipped')\n ->where('total', '>', 100) // Atenção: essa condição se aplica ao orWhere anterior!\n ->get();\n\n// SQL: ... WHERE status = 'paid' OR (status = 'shipped' AND total > 100)\n\n⚠️ Importante! No último exemplo, o where total > 100 se aplica apenas a status = 'shipped'. Se você quiser que ambos os status tenham total > 100, veja o próximo tópico.
3. Agrupamento de condições com closures (AND + OR juntos)
\n\nAqui chegamos à ferramenta mais poderosa. Quando precisar criar um grupo de condições entre parênteses, use uma closure dentro do where():
<?php\n\n// Tarefa: encontrar pedidos com status "paid" ou "shipped",\n// mas com total > 100 em ambos os casos\n$orders = Order::where(function($query) {\n $query->where('status', 'paid')\n ->orWhere('status', 'shipped');\n })\n ->where('total', '>', 100)\n ->get();\n\n// SQL: ... WHERE (status = 'paid' OR status = 'shipped') AND total > 100\n\nAgora as condições estão agrupadas corretamente! Você pode aninhar closures quantas vezes precisar:
\n\n<?php\n\n// Filtro complexo para análise de dados\n$data = Sale::where('date', '>=', '2024-01-01')\n ->where(function($q) {\n $q->where('amount', '>', 10000)\n ->orWhere('is_vip', true);\n })\n ->where(function($q) {\n $q->