Die Klasse Illuminate\Support\Collection ist ein fluenter Wrapper für Array-Daten.
Statt einzelne PHP-Standardfunktionen für Arrays aneinanderzureihen, können Sie Daten mit Methoden-Chaining intuitiv verarbeiten.
Collections sind immutable (unveränderlich). Jede Methode verändert die ursprüngliche Collection nicht, sondern liefert eine neue Instanz zurück. Sie können sicher arbeiten, ohne die Originaldaten zu verlieren.
Reduziert ähnlich wie reduce, die Callback-Funktion muss aber keinen Rückgabewert liefern. Praktisch, wenn Sie ein bestehendes Objekt direkt mutieren möchten.
class OrderStats{ public int $total = 0; public int $count = 0;}$orders = collect([ ['amount' => 100], ['amount' => 250], ['amount' => 50],]);$stats = $orders->reduceInto(new OrderStats, function (OrderStats $stats, array $order) { $stats->total += $order['amount']; $stats->count++;});$stats->total; // 400$stats->count; // 3
Bei reduce wird der Rückgabewert der Callback zum nächsten $carry, was sich gut für primitive Werte eignet. reduceInto mutiert dagegen kontinuierlich ein Objekt und führt so zu übersichtlicherem Code.
Möchten Sie in einen Skalar oder ein Array aggregieren, verwenden Sie in der Callback eine Referenz (&).
$collection = collect([1, 2, 3, 4, 5]);$even = $collection->reduceInto([], function (array &$result, int $value) { if ($value % 2 === 0) { $result[] = $value; }});// [2, 4]
Die eigentliche Stärke von Collections liegt im Methoden-Chaining. Mehrere Operationen lassen sich verketten, sodass komplexe Datentransformationen in einem einzigen Ausdruck möglich werden.
Ergebnisse von Eloquent-Abfragen werden stets als Instanzen von Illuminate\Database\Eloquent\Collection zurückgegeben.
Diese erbt von der Basis-Collection, sodass alle oben gezeigten Methoden zur Verfügung stehen.
use App\Models\User;use App\Models\Order;// Ergebnis von get() ist eine Collection$users = User::where('is_active', true)->get(); // Collection// Collection-Methoden direkt verwendbar$adminEmails = User::all() ->filter(fn ($user) => $user->role === 'admin') ->pluck('email');// Auch bereits geladene Relationen sind Collections$orders = Order::with('items')->where('status', 'completed')->get();$summary = $orders->map(fn ($order) => [ 'id' => $order->id, 'customer' => $order->user->name, 'item_count' => $order->items->count(), 'total' => $order->items->sum('price'),]);
Filterung und Sortierung, die die Datenbank effizient erledigen kann, sollten Sie über den Query Builder (where, orderBy usw.) durchführen und nicht erst auf der Collection anwenden. Andernfalls laden Sie unnötige Daten in den Speicher.
Während gewöhnliche Collections die gesamten Daten in den Arbeitsspeicher laden, nutzt eine LazyCollection PHP-Generatoren und verarbeitet die Daten Element für Element.
Bei mehreren Zehntausend Datensätzen oder mehr sparen Sie damit deutlich Arbeitsspeicher.
use Illuminate\Support\LazyCollection;// Normale Collection: lädt alle Daten in den Speicher$users = User::all(); // 100.000 Einträge landen komplett im Speicher// LazyCollection: Element für ElementUser::cursor()->each(function (User $user) { // Nutzer einzeln verarbeiten // Immer nur ein Element wird im Speicher gehalten});
use App\Models\Order;// Alle Bestellungen einzeln verarbeiten (speicheroptimal)Order::cursor() ->filter(fn ($order) => $order->amount > 10000) ->each(fn ($order) => $order->sendConfirmationEmail());// Mit cursor() Datensatzweise abrufen und mit filter/each in einer Pipeline verarbeitenOrder::where('status', 'completed') ->cursor() ->filter(fn ($order) => $order->amount > 10000) ->each(fn ($order) => $order->sendConfirmationEmail());
cursor() holt Datensätze einzeln aus der Datenbank und spart bei großen Ergebnismengen erheblich Speicher. Beachten Sie jedoch, dass die Datenbankverbindung bis zum Ende der Verarbeitung offen bleibt.