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

# Higher-order messages van collecties

> Hoe higher-order messages van collecties werken en hoe je ze in de praktijk gebruikt

## Wat zijn higher-order messages

Higher-order messages zijn een syntaxis waarmee je collectiemethodes aanroept in de vorm van property-toegang. Zonder een callback te schrijven kun je op elk element een methode aanroepen of een property ophalen.

```php theme={null}
// De gewone manier
$names = $users->map(fn ($user) => $user->name);

// Met een higher-order message
$names = $users->map->name;
```

`$users->map->name` betekent "haal van elke gebruiker de property `name` op en `map` daarover".

## Hoe het werkt — HigherOrderCollectionProxy

Wanneer je zoals bij `$collection->map` als property toegang zoekt, wordt `__get()` van de trait `EnumeratesValues` aangeroepen.

```php theme={null}
// src/Illuminate/Collections/Traits/EnumeratesValues.php
public function __get($key)
{
    if (! in_array($key, static::$proxies)) {
        throw new Exception("Property [{$key}] does not exist on this collection instance.");
    }

    return new HigherOrderCollectionProxy($this, $key);
}
```

Als de naam voorkomt in `$proxies`, krijg je een instantie van `HigherOrderCollectionProxy` terug. Deze proxy houdt twee dingen bij: de collectie en de methodenaam.

### Property-toegang via \_\_get proxyen

Als je vervolgens een property benadert (`->name`), wordt `__get()` van de proxy aangeroepen.

```php theme={null}
// src/Illuminate/Collections/HigherOrderCollectionProxy.php
public function __get($key)
{
    return $this->collection->{$this->method}(function ($value) use ($key) {
        return is_array($value) ? $value[$key] : $value->{$key};
    });
}
```

Met andere woorden: `$users->map->name` is gelijk aan het volgende.

```php theme={null}
$users->map(fn ($user) => $user->name);
```

### Methode-aanroepen via \_\_call proxyen

Als je vervolgens een methode aanroept (`->activate()`), wordt `__call()` van de proxy aangeroepen.

```php theme={null}
public function __call($method, $parameters)
{
    return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
        return is_string($value)
            ? $value::{$method}(...$parameters)
            : $value->{$method}(...$parameters);
    });
}
```

`$users->each->activate()` is gelijk aan het volgende.

```php theme={null}
$users->each(fn ($user) => $user->activate());
```

## Overzicht van ondersteunde methodes

De methodes die je als higher-order message kunt gebruiken, zijn gedefinieerd in de array `$proxies`.

```php theme={null}
protected static $proxies = [
    'average', 'avg',
    'contains', 'doesntContain', 'some',
    'each', 'every',
    'filter', 'reject',
    'first', 'last',
    'flatMap', 'map',
    'groupBy', 'keyBy',
    'hasMany', 'hasSole',
    'max', 'min', 'sum', 'percentage',
    'partition',
    'skipUntil', 'skipWhile',
    'sortBy', 'sortByDesc',
    'takeUntil', 'takeWhile',
    'unique',
    'unless', 'until', 'when',
];
```

Een eigen methode toevoegen doe je met `Collection::proxy()`.

```php theme={null}
Collection::proxy('myCustomMethod');
```

## Praktische use cases

### Collecties van Eloquent-modellen

Higher-order messages zijn vooral handig bij Eloquent-collecties.

```php theme={null}
$users = User::with('posts')->get();

// Methode-aanroep: de status van elke gebruiker bijwerken
$users->each->markAsVerified();

// Property-toegang: alleen de namen ophalen
$names = $users->map->name;

// Argumenten meegeven aan een methode
$users->each->sendPasswordReset('ja');

// E-mail versturen
$users->each->notify(new WelcomeNotification);
```

### Filteren

```php theme={null}
$activeUsers = $users->filter->isActive();

// Alleen gebruikers behouden voor wie isActive() true teruggeeft
// Gelijk aan $users->filter(fn ($user) => $user->isActive())

$inactiveUsers = $users->reject->isActive();
```

### Aggregatie

```php theme={null}
// Som van de property post_count van elke gebruiker
$totalPosts = $users->sum->post_count;

// Maximum van de score van elke gebruiker
$highestScore = $users->max->score;

// Gemiddelde van de age van elke gebruiker
$averageAge = $users->avg->age;
```

### Groeperen en sorteren

```php theme={null}
// Groeperen op de property role
$grouped = $users->groupBy->role;

// Oplopend sorteren op de property name
$sorted = $users->sortBy->name;

// Aflopend sorteren op de property created_at
$sorted = $users->sortByDesc->created_at;
```

### Geneste structuren afvlakken met flatMap

```php theme={null}
// De posts-relatie van elke gebruiker uitvouwen tot één collectie
$posts = $users->flatMap->posts;
```

### Voorwaarden controleren

```php theme={null}
// Controleren of iedereen beheerder is
$allAdmins = $users->every->isAdmin();

// Controleren of er minstens één actieve gebruiker is
$hasActive = $users->contains->isActive();

// Controleren of iedereen een bepaald abonnement heeft
$allPro = $users->every->hasPlan('pro');
```

### Stringcollecties

Ze werken ook op collecties waarvan de waarden strings zijn. De `__call()` van de proxy roept in het geval van een string de methode statisch aan.

```php theme={null}
$names = collect(['alice', 'bob', 'charlie']);

// Voor stringcollecties is een closure explicieter
$upper = $names->map(fn ($name) => strtoupper($name));
// ['ALICE', 'BOB', 'CHARLIE']
```

<Info>
  Voor higher-order messages op stringcollecties moet de methode statisch gedefinieerd zijn op het stringtype. Normaal gesproken is het natuurlijker om ze te gebruiken met collecties van Eloquent-modellen of eigen klassen.
</Info>

## Vergelijking met gewone closures

Higher-order messages zijn beknopt, maar niet in alle gevallen bruikbaar.

```php theme={null}
// Higher-order message: geschikt voor eenvoudige property-toegang en methode-aanroepen
$emails = $users->map->email;
$users->each->sendWelcomeMail();
$admins = $users->filter->isAdmin();

// Closure: geschikt voor complexe logica of wanneer argumenten nodig zijn
$formatted = $users->map(function ($user) {
    return "{$user->name} <{$user->email}>";
});

$filtered = $users->filter(function ($user) use ($minAge, $role) {
    return $user->age >= $minAge && $user->role === $role;
});
```

<Tip>
  Als je "van elk element dezelfde property wilt ophalen" of "op elk element dezelfde methode wilt aanroepen", zijn higher-order messages beter leesbaar. Bij complexe voorwaarden of dynamische argumenten gebruik je closures.
</Tip>

## Higher-order messages gebruiken met eigen klassen

Om via de trait `EnumeratesValues` het mechanisme van `HigherOrderCollectionProxy` te benutten, roep je `Collection::proxy()` aan om de methode toe te voegen aan de proxy-doelen.

```php theme={null}
namespace App\Providers;

use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Een eigen macro toevoegen aan de proxy-doelen
        Collection::macro('active', function () {
            return $this->filter(fn ($item) => $item->isActive());
        });

        Collection::proxy('active');
    }
}
```

```php theme={null}
// Na registratie bruikbaar als higher-order message
$activeUsers = $users->active;
```

## Volgende stap

<Card title="Conditionable-trait" icon="git-branch" href="/nl/advanced/conditionable">
  Leer de interne implementatie van `when()` / `unless()` en hoe je die toepast op de Query Builder en eigen klassen.
</Card>


## Related topics

- [Eloquent-collecties](/nl/eloquent-collections.md)
- [Collection deep dive](/nl/advanced/collection-deep-dive.md)
- [Conditionable-trait](/nl/advanced/conditionable.md)
- [Eloquent API-resources](/nl/eloquent-resources.md)
- [Eloquent-serialisatie](/nl/eloquent-serialization.md)
