Komplexe WHERE-Abfragen in Laravel Eloquent: 4 Methoden mit Beispielen
\n\nStellen Sie sich vor: Sie entwickeln einen Online-Shop mit Laravel. Sie müssen alle Produkte finden, die zwischen 1000 und 5000 Euro kosten, auf Lager sind, aber nicht aus der Kategorie "Sale" stammen und nach dem 1. Januar 2024 erstellt wurden. Wie machen Sie das mit einer einzigen Abfrage, ohne die Performance zu beeinträchtigen?
\n\nDiese Frage ist eine der häufigsten auf Stack Overflow (tausende Aufrufe!). Und das zu Recht: Die Fähigkeit, komplexe WHERE-Bedingungen in Laravel Eloquent zu erstellen, unterscheidet Anfänger von erfahrenen Entwicklern.
\n\nIn diesem Artikel zeige ich Ihnen 4 bewährte Methoden, um mehrere WHERE-Bedingungen zu erstellen. Sie erfahren, wann Sie Arrays, wann Closures verwenden, wie Sie Bedingungen gruppieren und SQL-Injection vermeiden. Los geht's!
\n\n\n\n
1. Basis-Methode: Array von Bedingungen (für einfache AND-Verknüpfungen)
\n\nDer einfachste Fall: Alle Bedingungen werden mit AND verknüpft. Laravel erlaubt es, ein einfaches Array an where() zu übergeben:
<?php\n\n// Wir suchen aktive Benutzer aus Deutschland, erstellt im Jahr 2024\n$users = User::where([\n ['status', '=', 'active'],\n ['country', '=', 'Germany'],\n ['created_at', '>=', '2024-01-01'],\n])->get();\n\n// SQL: SELECT * FROM users WHERE status = 'active' AND country = 'Germany' AND created_at >= '2024-01-01'\n\nWann verwenden: Bei 2-5 einfachen Bedingungen mit dem Operator = oder >. Der Code ist lesbar, aber nicht flexibel.
Nachteil: Wenn Sie AND und OR mischen müssen, ist ein Array nicht geeignet.
2. Methodenverkettung mit where() (für dynamische Bedingungen)
\n\nDies ist die beliebteste Methode unter Entwicklern. Sie rufen einfach mehrmals where() hintereinander auf:
<?php\n\n$products = Product::where('price', '>', 1000)\n ->where('price', '<', 5000)\n ->where('in_stock', true)\n ->where('category_id', '!=', 5)\n ->get();\n\n// SQL: ... WHERE price > 1000 AND price < 5000 AND in_stock = 1 AND category_id <> 5\n\nTrick: Sie können dies mit anderen Bedingungen kombinieren:
\n\n<?php\n\n// "ODER"-Bedingung innerhalb der Kette\n$orders = Order::where('status', 'paid')\n ->orWhere('status', 'shipped')\n ->where('total', '>', 100) // Achtung: Diese Bedingung bezieht sich auf das vorherige orWhere!\n ->get();\n\n// SQL: ... WHERE status = 'paid' OR (status = 'shipped' AND total > 100)\n\n⚠️ Wichtig! Im letzten Beispiel bezieht sich WHERE total > 100 nur auf status = 'shipped'. Wenn beide Status die Bedingung total > 100 erfüllen sollen, lesen Sie den nächsten Punkt.
3. Gruppierung von Bedingungen mit Closures (AND + OR kombiniert)
\n\nHier kommen wir zum leistungsstärksten Werkzeug. Wenn Sie eine Gruppe von Bedingungen in Klammern setzen müssen, verwenden Sie ein Closure innerhalb von where():
<?php\n\n// Aufgabe: Bestellungen mit Status "paid" oder "shipped" finden,\n// aber total muss in beiden Fällen > 100 sein\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\nJetzt sind die Bedingungen korrekt gruppiert! Sie können Closures beliebig tief verschachteln:
\n\n<?php\n\n// Komplexer Filter für Analysen\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->where('region', 'Europe')\n ->orWhere('region', 'Asia');\n })\n ->get();\n\n// SQL: ... WHERE date >= '2024-01-01' AND (amount > 10000 OR is_vip = 1) AND (region = 'Europe' OR region = 'Asia')\n\nProfi-Tipp: Verwenden Sie aussagekräftige Variablennamen wie $query oder $q in Closures, um die Lesbarkeit zu erhöhen.
4. whereHas für Beziehungen (komplexe Bedingungen über verknüpfte Tabellen)
\n\nOft müssen Sie Bedingungen nicht nur auf die aktuelle Tabelle, sondern auch auf verknüpfte Tabellen anwenden. Hier kommt whereHas ins Spiel:
<?php\n\n// Alle Benutzer finden, die mindestens eine Bestellung über 500 Euro haben\n$users = User::whereHas('orders', function($query) {\n $query->where('total', '>', 500);\n })->get();\n\n// SQL: SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id AND total > 500)\n\nErweitertes Beispiel mit mehreren Bedingungen:
\n\n<?php\n\n// Produkte finden, die in Bestellungen aus dem Jahr 2024 mit Status "completed" vorkommen\n$products = Product::whereHas('orderItems.order', function($query) {\n $query->where('status', 'completed')\n ->whereYear('created_at', 2024);\n })->get();\n\n// SQL: ... WHERE EXISTS (SELECT 1 FROM order_items ... WHERE status = 'completed' AND YEAR(created_at) = 2024)\n\nAlternative: whereDoesntHave für Bedingungen, die nicht zutreffen sollen:
\n\n<?php\n\n// Benutzer ohne abgeschlossene Bestellungen\n$inactiveUsers = User::whereDoesntHave('orders', function($query) {\n $query->where('status', 'completed');\n })->get();\n\n\n\n
Zusammenfassung: Wann welche Methode?
\n\n| Methode | \nAm besten geeignet für | \n
|---|---|
| Array in where() | \nEinfache AND-Bedingungen, 2-5 Stück | \n
| Methodenverkettung | \nDynamische Bedingungen, gemischte Operatoren | \n
| Closures (Gruppierung) | \nKomplexe Logik mit AND/OR-Kombinationen | \n
| whereHas / whereDoesntHave | \nBedingungen über verknüpfte Tabellen (Beziehungen) | \n
Bonus-Tipp: Verwenden Sie whereBetween für Bereichsabfragen und whereIn für mehrere Werte, um Ihren Code noch sauberer zu halten:
<?php\n\n$products = Product::whereBetween('price', [1000, 5000])\n ->whereIn('category_id', [1, 3, 7])\n ->where('in_stock', true)\n ->get();\n\n// SQL: ... WHERE price BETWEEN 1000 AND 5000 AND category_id IN (1, 3, 7) AND in_stock = 1\n\nJetzt sind Sie bestens gerüstet, um komplexe WHERE-Abfragen in Laravel Eloquent zu meistern. Probieren Sie die Methoden in Ihrem nächsten Projekt aus und optimieren Sie Ihre Datenbankabfragen!