Wenn du in Laravel die Datenschicht aufbaust, ist die erste große Entscheidung die zwischen dem Eloquent-ORM und dem Query Builder; das Duo eloquent query builder ruht eigentlich auf derselben Grundlage, arbeitet aber auf unterschiedlichen Abstraktionsebenen. Eloquent bildet Tabellen auf Modellobjekte ab und bringt Beziehungen, Events und Mutatoren mit. Der Query Builder dagegen bleibt über eine fließende Schnittstelle viel näher an SQL. Auf die Frage, welcher der „richtige" ist, gibt es keine einzige Antwort: Die richtige Antwort hängt davon ab, welche Aufgabe konkret vor dir liegt.
Beide teilen denselben Kern
Ein wichtiger Punkt: Eloquent ist auf dem Query Builder aufgebaut. Wenn du where() auf einem Modell aufrufst, erreichst du im Hintergrund tatsächlich eine Query-Builder-Instanz. Eloquent ist also keine „langsame Alternative" — es ist eine höhere Ebene, die eine Objektschicht, Beziehungsverwaltung und Modell-Events über den Query Builder legt. Der Performance-Unterschied kommt nicht von der Engine selbst, sondern von der Arbeit, die diese zusätzliche Schicht leistet: jede Zeile in ein PHP-Objekt umzuwandeln (Hydration) und Beziehungen zu verwalten, hat seinen Preis.
Wann Eloquent glänzt
Eloquent hebt sich klar in CRUD-Szenarien hervor, in denen die Geschäftslogik zentral ist und du eine kleine bis mittlere Anzahl von Datensätzen liest und schreibst. Lesbarkeit und Wartbarkeit sind hier der eigentliche Gewinn:
- Beziehungen: du erreichst verknüpfte Daten in einer einzigen Zeile wie
$user->posts; mitwith()betreibst du Eager Loading und löst das N+1-Abfrageproblem. - Modell-Events: Events wie
creatingundsaved, Observer und Mutatoren/Casts laufen automatisch. - Soft Deletes, Timestamps, Scopes: die meiste wiederkehrende Logik wird über Traits und Scopes an einer Stelle gebündelt.
// N+1 mit Eager Loading verhindern
$posts = Post::with('author', 'comments')
->where('published', true)
->latest()
->get();
foreach ($posts as $post) {
echo $post->author->name; // keine zusätzliche Abfrage
}
Wann der Query Builder besser ist
Der Query Builder kommt ins Spiel, wenn du das Modellverhalten nicht brauchst und die Performance kritisch ist. Berichte über Tausende Zeilen, Massen-Updates, komplexe join- und Aggregat-Abfragen sind genau sein Gebiet. Da er nicht jede Zeile in ein Modellobjekt umwandelt, ist er leichter für Speicher und CPU.
// Eine direkte, leichte Reporting-Abfrage
$stats = DB::table('orders')
->select('user_id', DB::raw('SUM(total) as total'))
->where('created_at', '>=', now()->subMonth())
->groupBy('user_id')
->having('total', '>', 1000)
->get();
Hier willst du ohnehin kein Modellobjekt, keine Beziehung und kein Event; du willst nur die Zahlen aufsummieren und zurückgeben. Der Query Builder erledigt das ohne Hydration-Overhead und gibt stdClass-Objekte zurück.
Denke beim Performance-Kompromiss in Zahlen
In der Praxis ist der Unterschied beim Abruf eines einzelnen Datensatzes selten spürbar; es geht alles um die Skalierung. Es gibt keine messbare Lücke zwischen dem Abruf von 50 Zeilen mit Eloquent oder mit dem Query Builder. Aber wenn du für einen Export-Job über 50.000 Zeilen iterierst, verbraucht das Erstellen eines Modells für jede Zeile ernsthaft Speicher. Ein paar praktische Regeln:
- Große Lesevorgänge + Verarbeitung: streame Zeilen mit dem Query Builder oder den Methoden
cursor()/lazy()von Eloquent, statt alles in den Speicher zu laden. - Massen-Updates:
Model::where(...)->update([...])läuft als einzelne Abfrage, löst aber keine Modell-Events aus; nutze es im Bewusstsein dessen. - Wenn du nur wenige Spalten brauchst: begrenze die Spalten mit
select()auch in Eloquent; unnötige Daten zu laden verlangsamt die Hydration.
// 50.000 Zeilen verarbeiten, ohne sie in den Speicher zu stapeln
Order::where('exported', false)
->lazy()
->each(function ($order) {
// ein Modell nach dem anderen, wenig Speicher
});
Beide zusammen zu nutzen ist der realistischste Weg
Statt eines Richtig/Falsch-Dilemmas nutzen die meisten Projekte beide. CRUD und Formularverarbeitung mit Eloquent zu schreiben und schwere Dashboard-Abfragen dem Query Builder zu überlassen, in derselben Anwendung, ist völlig normal. Du kannst innerhalb von Eloquent sogar dort, wo nötig, mit whereRaw() oder selectRaw() auf rohes SQL hinabsteigen und die Performance feinjustieren, während du die Modellvorteile behältst. Wenn du auf rohe Abfragen hinabsteigst, vernachlässige das Parameter-Binding nicht; eine Verwendung wie whereRaw('price > ?', [$min]) schützt dich vor SQL-Injection.
Fragen, die du bei der Entscheidung stellen solltest
- Sind Beziehungen, Events oder Casts für diese Aufgabe nötig? Wenn ja, Eloquent.
- Wie viele Zeilen kommen zurück, und werde ich sie alle in Objekte umwandeln? Wenn viele, Query Builder oder
lazy(). - Ist das ein Hot Path (läuft es bei jeder Anfrage)? Wenn ja, miss und vereinfache bei Bedarf.
- Ist Lesbarkeit oder eine Millisekunde wertvoller? Für die meisten Bildschirme gewinnt die Lesbarkeit.
Häufige Fragen
Ist Eloquent wirklich langsamer als der Query Builder?
Es ist nicht die Engine allein — das Umwandeln jeder Zeile in ein PHP-Objekt (Hydration) und das Verwalten von Beziehungen verlangsamen es. Bei wenigen Datensätzen ist der Unterschied unmerklich; über Tausende Zeilen ist der Query Builder spürbar leichter.
Kann ich rohes SQL innerhalb von Eloquent verwenden?
Ja. Du kannst rohe Fragmente mit whereRaw(), selectRaw() und DB::raw() hinzufügen. Übergib Werte immer über Parameter-Binding, statt Strings direkt zu verketten.
Welcher sollte meine Standardwahl sein?
Beginne mit Eloquent; der Code bleibt sauberer und leichter zu warten. Sobald du profilierst und einen Engpass findest, verschiebe genau diese Abfrage zum Query Builder oder zu einer Streaming-Methode.
Ist die Datenschicht deiner Laravel-App langsam, oder weißt du einfach nicht, wo du anfangen sollst? Ich helfe dir, eine skalierbare Architektur aufzubauen, die Eloquent und den Query Builder an den richtigen Stellen einsetzt. Nimm Kontakt auf, um über dein Projekt zu sprechen.