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

# Messages d'ordre supérieur des collections

> Fonctionnement et utilisation pratique des messages d'ordre supérieur (Higher-order Messages) des collections.

## Qu'est-ce qu'un message d'ordre supérieur

Les messages d'ordre supérieur (Higher-order Messages) sont une syntaxe qui permet d'appeler les méthodes d'une collection sous la forme d'un accès à une propriété. Sans écrire de callback, vous pouvez appeler une méthode ou récupérer une propriété sur chaque élément.

```php theme={null}
// Écriture classique
$names = $users->map(fn ($user) => $user->name);

// Écriture avec un message d'ordre supérieur
$names = $users->map->name;
```

`$users->map->name` signifie « extraire la propriété `name` de chaque utilisateur et faire un `map` ».

## Fonctionnement — HigherOrderCollectionProxy

Lorsque vous accédez à `$collection->map` comme à une propriété, la méthode `__get()` du trait `EnumeratesValues` est appelée.

```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);
}
```

Si le nom de la méthode figure dans `$proxies`, une instance de `HigherOrderCollectionProxy` est retournée. Ce proxy conserve deux informations : la collection et le nom de la méthode.

### Proxy d'accès aux propriétés via \_\_get

Si vous accédez ensuite à une propriété (`->name`), le `__get()` du proxy est appelé.

```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};
    });
}
```

Autrement dit, `$users->map->name` équivaut à :

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

### Proxy d'appel de méthode via \_\_call

Si vous appelez ensuite une méthode (`->activate()`), le `__call()` du proxy est invoqué.

```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()` équivaut à :

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

## Liste des méthodes prises en charge

Les méthodes utilisables comme messages d'ordre supérieur sont définies dans le tableau `$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',
];
```

Pour ajouter une méthode personnalisée, utilisez `Collection::proxy()`.

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

## Cas d'utilisation pratiques

### Collections de modèles Eloquent

Les messages d'ordre supérieur sont particulièrement pratiques avec les collections Eloquent.

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

// Appel de méthode : mettre à jour le statut de chaque utilisateur
$users->each->markAsVerified();

// Accès à une propriété : ne récupérer que les noms
$names = $users->map->name;

// Passer un argument à la méthode
$users->each->sendPasswordReset('ja');

// Envoi d'e-mail
$users->each->notify(new WelcomeNotification);
```

### Filtrage

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

// Ne garde que les utilisateurs pour lesquels isActive() renvoie true
// Équivalent à $users->filter(fn ($user) => $user->isActive())

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

### Agrégation

```php theme={null}
// Somme des propriétés post_count de chaque utilisateur
$totalPosts = $users->sum->post_count;

// Score maximum parmi les propriétés score
$highestScore = $users->max->score;

// Moyenne des âges
$averageAge = $users->avg->age;
```

### Groupement / tri

```php theme={null}
// Groupement par propriété role
$grouped = $users->groupBy->role;

// Tri croissant par propriété name
$sorted = $users->sortBy->name;

// Tri décroissant par propriété created_at
$sorted = $users->sortByDesc->created_at;
```

### Déployer une imbrication avec flatMap

```php theme={null}
// Déploie la relation posts de chaque utilisateur en une seule collection
$posts = $users->flatMap->posts;
```

### Vérification de conditions

```php theme={null}
// Vérifier si tout le monde est administrateur
$allAdmins = $users->every->isAdmin();

// Vérifier si au moins un utilisateur est actif
$hasActive = $users->contains->isActive();

// Vérifier si tout le monde a un plan spécifique
$allPro = $users->every->hasPlan('pro');
```

### Collections de chaînes

Cela fonctionne aussi pour des collections dont les valeurs sont des chaînes. Le `__call()` du proxy les appelle alors comme méthodes statiques.

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

// Pour une collection de chaînes, une closure reste plus explicite
$upper = $names->map(fn ($name) => strtoupper($name));
// ['ALICE', 'BOB', 'CHARLIE']
```

<Info>
  Utiliser des messages d'ordre supérieur sur une collection de chaînes nécessite que la méthode soit définie statiquement sur le type string. En pratique, c'est plus naturel avec des collections de modèles Eloquent ou de classes maison.
</Info>

## Comparaison avec les closures classiques

Les messages d'ordre supérieur sont concis, mais ne conviennent pas à tous les cas.

```php theme={null}
// Messages d'ordre supérieur : parfaits pour un accès simple à une propriété ou un appel de méthode
$emails = $users->map->email;
$users->each->sendWelcomeMail();
$admins = $users->filter->isAdmin();

// Closures : préférables lorsque la logique est complexe ou qu'un argument est nécessaire
$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>
  Pour « extraire la même propriété de chaque élément » ou « appeler la même méthode sur chaque élément », les messages d'ordre supérieur sont plus lisibles. Si la condition est complexe ou si les arguments sont dynamiques, préférez les closures.
</Tip>

## Utiliser des messages d'ordre supérieur avec vos classes personnalisées

Pour bénéficier du mécanisme `HigherOrderCollectionProxy` via le trait `EnumeratesValues`, appelez `Collection::proxy()` pour ajouter la méthode aux cibles du proxy.

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

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

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Ajoute une macro personnalisée aux cibles du proxy
        Collection::macro('active', function () {
            return $this->filter(fn ($item) => $item->isActive());
        });

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

```php theme={null}
// Après enregistrement, utilisable comme message d'ordre supérieur
$activeUsers = $users->active;
```

## Étapes suivantes

<Card title="Trait Conditionable" icon="git-branch" href="/fr/advanced/conditionable">
  Découvrez l'implémentation interne de `when()` / `unless()` et son application à QueryBuilder ou à vos propres classes.
</Card>


## Related topics

- [Collection Deep Dive](/fr/advanced/collection-deep-dive.md)
- [Trait Conditionable](/fr/advanced/conditionable.md)
- [Eloquent API Resources](/fr/eloquent-resources.md)
- [Collections](/fr/collections.md)
- [Eloquent Bootable Traits](/fr/advanced/eloquent-bootable-traits.md)
