> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Collections

> Leer hoe je data efficiënt bewerkt met de Collection-klasse van Laravel.

## Wat zijn collections

De klasse `Illuminate\Support\Collection` is een vloeiende wrapper voor het werken met arraydata.
In plaats van de standaard PHP-arrayfuncties afzonderlijk aan te roepen, kun je data intuïtief bewerken met method chaining.

```php theme={null}
// Gewone arraybewerkingen
$names = array_filter(
    array_map(fn ($user) => $user['name'], $users),
    fn ($name) => $name !== null
);

// Met een collection
$names = collect($users)
    ->pluck('name')
    ->filter()
    ->values();
```

<Info>
  Collections zijn **immutable** (onveranderlijk). Elke methode wijzigt de oorspronkelijke collection niet, maar geeft een nieuwe collection-instantie terug. Zo kun je veilig werken terwijl de oorspronkelijke data behouden blijft.
</Info>

## Een collection maken

### De `collect()` helper

Dit is de meest gebruikte manier. Je geeft een array door om een collection te maken.

```php theme={null}
use Illuminate\Support\Collection;

// Een collection maken van een array
$users = collect([
    ['name' => 'Yamada Taro', 'age' => 28, 'role' => 'admin'],
    ['name' => 'Suzuki Hanako', 'age' => 34, 'role' => 'editor'],
    ['name' => 'Sato Jiro', 'age' => 22, 'role' => 'viewer'],
]);

// Geneste arrays kunnen ook
$products = collect([
    ['name' => 'Laptop', 'price' => 120000, 'stock' => 5],
    ['name' => 'Muis', 'price' => 3500, 'stock' => 20],
    ['name' => 'Toetsenbord', 'price' => 8000, 'stock' => 12],
]);
```

### `Collection::make()`

Gelijkwaardig aan `collect()`. Gebruik dit als je liever in facade-stijl schrijft.

```php theme={null}
$collection = Collection::make([1, 2, 3]);
```

### `Collection::fromJson()`

Maakt een collection van een JSON-string. Handig bij het verwerken van responses van externe API's.

```php theme={null}
$collection = Collection::fromJson('[{"name":"Yamada Taro"},{"name":"Suzuki Hanako"}]');
```

## Veelgebruikte methoden

### `map` — elk element transformeren

Past een bewerking toe op elk element van de collection en geeft een nieuwe, getransformeerde collection terug.

```php theme={null}
$users = collect([
    ['name' => 'Yamada Taro', 'email' => 'yamada@example.com'],
    ['name' => 'Suzuki Hanako', 'email' => 'suzuki@example.com'],
]);

// E-mailadressen maskeren voor weergave
$masked = $users->map(function (array $user) {
    $parts = explode('@', $user['email']);
    return [
        'name' => $user['name'],
        'email' => substr($parts[0], 0, 2) . '***@' . $parts[1],
    ];
});

// [['name' => 'Yamada Taro', 'email' => 'ya***@example.com'], ...]
```

### `filter` / `reject` — filteren op voorwaarde

`filter()` houdt alleen de elementen die aan de voorwaarde voldoen, `reject()` verwijdert juist de elementen die aan de voorwaarde voldoen.

```php theme={null}
$products = collect([
    ['name' => 'Laptop', 'price' => 120000, 'in_stock' => true],
    ['name' => 'Muis', 'price' => 3500, 'in_stock' => false],
    ['name' => 'Toetsenbord', 'price' => 8000, 'in_stock' => true],
]);

// Alleen producten op voorraad ophalen
$inStock = $products->filter(fn ($product) => $product['in_stock']);

// Producten zonder voorraad uitsluiten (reject is de inverse van filter)
$available = $products->reject(fn ($product) => ! $product['in_stock']);

// filter() zonder argument verwijdert falsy waarden
$names = collect(['Yamada', '', null, 'Suzuki', false])->filter()->values();
// ['Yamada', 'Suzuki']
```

<Tip>
  Na `filter()` ontstaan er gaten in de indexen. Roep `values()` aan om ze opnieuw te nummeren vanaf 0.
</Tip>

### `first` / `last` — één element ophalen

Geeft het eerste of laatste element terug dat aan de voorwaarde voldoet.

```php theme={null}
$orders = collect([
    ['id' => 1, 'status' => 'shipped', 'amount' => 5000],
    ['id' => 2, 'status' => 'pending', 'amount' => 12000],
    ['id' => 3, 'status' => 'pending', 'amount' => 3500],
]);

// De eerste onverwerkte bestelling ophalen
$nextOrder = $orders->first(fn ($order) => $order['status'] === 'pending');
// ['id' => 2, 'status' => 'pending', 'amount' => 12000]

// Standaardwaarde als er geen match is
$order = $orders->first(fn ($order) => $order['status'] === 'cancelled', null);

// Het laatste element
$latest = $orders->last();
```

### `pluck` — alleen de waarden van een specifieke sleutel ophalen

Haalt alleen een specifiek veld uit geneste arrays of modellen.

```php theme={null}
$users = collect([
    ['id' => 1, 'name' => 'Yamada Taro', 'department' => 'Ontwikkeling'],
    ['id' => 2, 'name' => 'Suzuki Hanako', 'department' => 'Verkoop'],
    ['id' => 3, 'name' => 'Sato Jiro', 'department' => 'Ontwikkeling'],
]);

// Alleen de namen ophalen
$names = $users->pluck('name');
// ['Yamada Taro', 'Suzuki Hanako', 'Sato Jiro']

// Mappen met id als sleutel
$nameById = $users->pluck('name', 'id');
// [1 => 'Yamada Taro', 2 => 'Suzuki Hanako', 3 => 'Sato Jiro']
```

### `groupBy` — groeperen op een specifieke sleutel

```php theme={null}
$users = collect([
    ['name' => 'Yamada Taro', 'department' => 'Ontwikkeling'],
    ['name' => 'Suzuki Hanako', 'department' => 'Verkoop'],
    ['name' => 'Sato Jiro', 'department' => 'Ontwikkeling'],
    ['name' => 'Tanaka Misaki', 'department' => 'Verkoop'],
]);

$byDepartment = $users->groupBy('department');
// [
//   'Ontwikkeling' => [['name' => 'Yamada Taro', ...], ['name' => 'Sato Jiro', ...]],
//   'Verkoop' => [['name' => 'Suzuki Hanako', ...], ['name' => 'Tanaka Misaki', ...]],
// ]

// De groepssleutel dynamisch bepalen met een closure
$byFirstChar = $users->groupBy(fn ($user) => mb_substr($user['name'], 0, 1));
```

### `sortBy` / `sortByDesc` — sorteren

```php theme={null}
$products = collect([
    ['name' => 'Laptop', 'price' => 120000],
    ['name' => 'Muis', 'price' => 3500],
    ['name' => 'Toetsenbord', 'price' => 8000],
]);

// Oplopend op prijs
$cheapFirst = $products->sortBy('price');

// Aflopend op prijs
$expensiveFirst = $products->sortByDesc('price');

// Sorteren op meerdere sleutels
$sorted = $products->sortBy([
    ['price', 'asc'],
    ['name', 'asc'],
]);
```

### `each` — een bewerking uitvoeren op elk element

Gebruik dit voor bewerkingen met bijwerkingen (logging, e-mails versturen, enz.). De collection zelf wordt niet gewijzigd.

```php theme={null}
$orders = collect([
    ['id' => 1, 'user_id' => 10, 'amount' => 5000],
    ['id' => 2, 'user_id' => 11, 'amount' => 12000],
]);

$orders->each(function (array $order) {
    \Log::info("Bestelling #{$order['id']} wordt verwerkt", ['amount' => $order['amount']]);
    // Notificaties versturen, naar een queue dispatchen, enz.
});

// Door false terug te geven kun je de verwerking voortijdig stoppen
$orders->each(function (array $order) {
    if ($order['amount'] > 10000) {
        return false; // De lus verlaten
    }
    // ...
});
```

### `flatMap` — mappen en één niveau afvlakken

Transformeert elk element naar een array en maakt het geheel plat tot één dimensie.

```php theme={null}
$users = collect([
    ['name' => 'Yamada Taro', 'tags' => ['php', 'laravel']],
    ['name' => 'Suzuki Hanako', 'tags' => ['javascript', 'vue']],
]);

// De tags van alle gebruikers in een platte lijst
$allTags = $users->flatMap(fn ($user) => $user['tags']);
// ['php', 'laravel', 'javascript', 'vue']
```

### `reduce` — aggregeren

Vouwt de hele collection samen tot één waarde.

```php theme={null}
$orders = collect([
    ['product' => 'Laptop', 'quantity' => 1, 'price' => 120000],
    ['product' => 'Muis', 'quantity' => 2, 'price' => 3500],
    ['product' => 'Toetsenbord', 'quantity' => 1, 'price' => 8000],
]);

// Het totaalbedrag berekenen
$total = $orders->reduce(
    fn ($carry, $order) => $carry + ($order['price'] * $order['quantity']),
    0
);
// 135000
```

<Tip>
  Voor een eenvoudige som kun je `sum()` gebruiken: `$orders->sum(fn ($o) => $o['price'] * $o['quantity'])`
</Tip>

### `reduceInto` — aggregeren in een object

Voert net als `reduce` een samenvouwbewerking uit, maar met het verschil dat de callback geen returnwaarde hoeft terug te geven. Handig wanneer je een bestaand object rechtstreeks wilt muteren.

```php theme={null}
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
```

<Tip>
  Bij `reduce` wordt de returnwaarde van de callback de volgende `$carry`, waardoor het geschikt is voor het aggregeren van primitieve waarden. `reduceInto` blijft hetzelfde object wijzigen, wat eenvoudigere code oplevert.
</Tip>

Wil je aggregeren in een scalar of array, gebruik dan pass-by-reference (`&`) in de callback.

```php theme={null}
$collection = collect([1, 2, 3, 4, 5]);

$even = $collection->reduceInto([], function (array &$result, int $value) {
    if ($value % 2 === 0) {
        $result[] = $value;
    }
});

// [2, 4]
```

### `chunk` — opsplitsen

Splitst een grote collection op in stukken van een opgegeven grootte. Handig voor batchverwerking of weergave op het scherm.

```php theme={null}
$users = collect(range(1, 100))->map(fn ($i) => ['id' => $i, 'name' => "Gebruiker{$i}"]);

// Opsplitsen in stukken van 10
$chunks = $users->chunk(10);
// $chunks->count() === 10

// Per batch verwerken
$chunks->each(function (\Illuminate\Support\Collection $batch) {
    // Databasebewerkingen of e-mails per batch, enz.
});
```

### `chunkBy` — opsplitsen op aangrenzende waarden

`chunkBy` groepeert "aangrenzende" elementen met dezelfde waarde voor een opgegeven sleutel of callback, en splitst ze op in meerdere kleinere collections. Zo kun je bijvoorbeeld naast elkaar liggende producten met dezelfde parent groeperen.

```php theme={null}
$chunks = $products->chunkBy('parent');
```

Anders dan bij `groupBy` komen elementen met dezelfde waarde die niet aangrenzend zijn in afzonderlijke chunks terecht.

```php theme={null}
$collection = collect([1, 1, 2, 2, 1]);

$chunks = $collection->chunkBy(fn (int $value) => $value);

$chunks->all();

// [[1, 1], [2, 2], [1]]
```

## Method chaining

De ware kracht van collections zit in method chaining. Je kunt meerdere bewerkingen aan elkaar koppelen en complexe datatransformaties in één expressie uitdrukken.

```php theme={null}
$orders = collect([
    ['customer' => 'Yamada Taro', 'status' => 'completed', 'amount' => 5000, 'category' => 'Elektronica'],
    ['customer' => 'Suzuki Hanako', 'status' => 'pending',   'amount' => 12000, 'category' => 'Elektronica'],
    ['customer' => 'Sato Jiro', 'status' => 'completed', 'amount' => 3500, 'category' => 'Kantoorartikelen'],
    ['customer' => 'Tanaka Misaki', 'status' => 'completed', 'amount' => 8000, 'category' => 'Elektronica'],
    ['customer' => 'Ito Kenichi', 'status' => 'cancelled', 'amount' => 2000, 'category' => 'Kantoorartikelen'],
]);

// Afgeronde elektronica-bestellingen aflopend op bedrag ophalen en alleen klantnaam en bedrag extraheren
$result = $orders
    ->filter(fn ($order) => $order['status'] === 'completed')
    ->filter(fn ($order) => $order['category'] === 'Elektronica')
    ->sortByDesc('amount')
    ->map(fn ($order) => [
        'customer' => $order['customer'],
        'amount'   => number_format($order['amount']) . ' yen',
    ])
    ->values();

// [
//   ['customer' => 'Tanaka Misaki', 'amount' => '8,000 yen'],
//   ['customer' => 'Yamada Taro', 'amount' => '5,000 yen'],
// ]
```

## Integratie met Eloquent

De resultaten van Eloquent-queries worden altijd teruggegeven als een `Illuminate\Database\Eloquent\Collection`-instantie.
Die erft van de basis-`Collection`, dus alle bovenstaande methoden zijn beschikbaar.

```php theme={null}
use App\Models\User;
use App\Models\Order;

// Het resultaat van get() is een collection
$users = User::where('is_active', true)->get(); // Collection

// Je kunt collection-methoden direct gebruiken
$adminEmails = User::all()
    ->filter(fn ($user) => $user->role === 'admin')
    ->pluck('email');

// Ook geladen relatiedata kun je met collection-methoden bewerken
$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'),
]);
```

<Warning>
  Filteren en sorteren dat de database kan afhandelen, doe je beter met de query builder (`where`, `orderBy`, enz.) in plaats van met collection-bewerkingen. Als je pas na de conversie naar een collection filtert, laad je onnodige data volledig in het geheugen.
</Warning>

### Eloquent-specifieke collection-methoden

`Eloquent\Collection` heeft extra methoden.

```php theme={null}
$users = User::all();

// Een model zoeken op ID
$user = $users->find(1);

// Een collection van primaire sleutels ophalen
$ids = $users->modelKeys(); // [1, 2, 3, ...]

// Relaties in één keer laden
$users->load('orders', 'profile');

// Verschil en doorsnede
$diff = $users->diff($otherUsers);
$intersect = $users->intersect($otherUsers);
```

## Lazy collections

Een gewone collection laadt alle data in het geheugen, maar een `LazyCollection` maakt gebruik van PHP-generators en verwerkt data één voor één.
Bij grote datasets van tienduizenden records of meer bespaar je zo geheugen.

```php theme={null}
use Illuminate\Support\LazyCollection;

// Gewone collection: alle data wordt in het geheugen geladen
$users = User::all(); // Bij 100.000 records staan er 100.000 in het geheugen

// LazyCollection: één voor één verwerken
User::cursor()->each(function (User $user) {
    // Gebruikers één voor één verwerken
    // Er staat altijd maar één record in het geheugen
});
```

### Een LazyCollection maken

```php theme={null}
use Illuminate\Support\LazyCollection;

// Maken vanuit een closure (generator)
$lazy = LazyCollection::make(function () {
    $handle = fopen('large-file.csv', 'r');

    while (($line = fgetcsv($handle)) !== false) {
        yield $line;
    }

    fclose($handle);
});

// De cursor()-methode van Eloquent geeft een LazyCollection terug
$lazy = User::where('is_active', true)->cursor();
```

### Batchverwerking van grote datasets

```php theme={null}
use App\Models\Order;

// Alle bestellingen één voor één verwerken (geheugenefficiënt)
Order::cursor()
    ->filter(fn ($order) => $order->amount > 10000)
    ->each(fn ($order) => $order->sendConfirmationEmail());

// Met cursor() alles record voor record ophalen en verwerken via een filter/each-pipeline
Order::where('status', 'completed')
    ->cursor()
    ->filter(fn ($order) => $order->amount > 10000)
    ->each(fn ($order) => $order->sendConfirmationEmail());
```

<Info>
  `cursor()` haalt records één voor één op uit de database, waardoor je bij het verwerken van grote hoeveelheden records flink geheugen bespaart. De databaseverbinding blijft wel open tot de verwerking is voltooid.
</Info>

### Pagineren met `take` en `skip`

```php theme={null}
$lazy = LazyCollection::make(function () {
    foreach (range(1, 1000000) as $i) {
        yield $i;
    }
});

// De eerste 1000 items overslaan en de volgende 100 ophalen
$page = $lazy->skip(1000)->take(100)->values();
```

## Samenvatting

<AccordionGroup>
  <Accordion title="Overzicht van veelgebruikte methoden">
    | Methode                       | Beschrijving                                             |
    | ----------------------------- | -------------------------------------------------------- |
    | `collect($array)`             | Een collection maken                                     |
    | `map($callback)`              | Elk element transformeren                                |
    | `filter($callback)`           | Filteren op voorwaarde                                   |
    | `reject($callback)`           | Elementen die aan de voorwaarde voldoen uitsluiten       |
    | `first($callback)`            | Het eerste element ophalen dat aan de voorwaarde voldoet |
    | `pluck($key)`                 | Waarden van een specifieke sleutel ophalen               |
    | `groupBy($key)`               | Groeperen op een specifieke sleutel                      |
    | `sortBy($key)`                | Oplopend sorteren                                        |
    | `sortByDesc($key)`            | Aflopend sorteren                                        |
    | `each($callback)`             | Een bewerking uitvoeren op elk element (bijwerkingen)    |
    | `flatMap($callback)`          | Mappen en afvlakken                                      |
    | `reduce($callback, $initial)` | Aggregeren tot één waarde                                |
    | `chunk($size)`                | Opsplitsen in stukken van een opgegeven grootte          |
    | `values()`                    | Indexen opnieuw nummeren                                 |
    | `sum($key)`                   | De som berekenen                                         |
    | `count()`                     | Het aantal ophalen                                       |
  </Accordion>

  <Accordion title="Collections vs arrayfuncties">
    Collections zijn veel beter leesbaar dan arrayfuncties.

    ```php theme={null}
    // Met arrayfuncties
    $result = array_values(array_filter(
        array_map(fn ($u) => $u['name'], $users),
        fn ($name) => strlen($name) > 2
    ));

    // Met een collection
    $result = collect($users)
        ->pluck('name')
        ->filter(fn ($name) => strlen($name) > 2)
        ->values()
        ->all();
    ```
  </Accordion>

  <Accordion title="Gewone collection vs LazyCollection">
    * **Gewone collection**: datasets van enkele honderden tot duizenden records. Eenvoudig en intuïtief.
    * **LazyCollection**: grote datasets van tienduizenden records of meer, of wanneer je geheugen wilt besparen. Vooral effectief in combinatie met `cursor()`.
    * `get()` van Eloquent geeft een gewone collection terug, `cursor()` een LazyCollection.
  </Accordion>
</AccordionGroup>


## Related topics

- [Collection deep dive](/nl/advanced/collection-deep-dive.md)
- [Eloquent-collecties](/nl/eloquent-collections.md)
- [Helperfuncties](/nl/helpers.md)
- [Higher-order messages van collecties](/nl/advanced/higher-order-messages.md)
- [Eloquent accessors, mutators en casts](/nl/eloquent-mutators.md)
