> ## 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 delle collection

> Meccanismo e utilizzo pratico degli higher-order messages delle collection.

## Cosa sono gli higher-order messages

Gli higher-order messages sono una sintassi che permette di chiamare i metodi di una collection nella forma di un accesso a proprietà. Senza scrivere callback, puoi invocare un metodo su ogni elemento o ottenerne una proprietà.

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

// scrittura con higher-order messages
$names = $users->map->name;
```

`$users->map->name` significa "estrai la proprietà `name` di ogni utente e applica `map`".

## Meccanismo — HigherOrderCollectionProxy

Accedendo come proprietà con `$collection->map`, viene invocato `__get()` del trait `EnumeratesValues`.

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

Se il nome del metodo è incluso in `$proxies`, viene restituita un'istanza di `HigherOrderCollectionProxy`. Questo proxy conserva due elementi: la collection e il nome del metodo.

### Proxy di accesso a proprietà con \_\_get

Accedendo poi a una proprietà (`->name`), viene invocato `__get()` del proxy.

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

In pratica `$users->map->name` è equivalente a:

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

### Proxy di chiamata a metodo con \_\_call

Chiamando poi un metodo (`->activate()`), viene invocato `__call()` del proxy.

```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()` è equivalente a:

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

## Elenco dei metodi supportati

I metodi utilizzabili come higher-order messages sono definiti nell'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',
];
```

Per aggiungere metodi personalizzati usa `Collection::proxy()`.

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

## Casi d'uso pratici

### Collection di modelli Eloquent

Gli higher-order messages sono particolarmente comodi con le collection Eloquent.

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

// chiamata a metodo: aggiorna lo stato di ogni utente
$users->each->markAsVerified();

// accesso a proprietà: estrai solo i nomi
$names = $users->map->name;

// passa argomenti al metodo
$users->each->sendPasswordReset('it');

// invio email
$users->each->notify(new WelcomeNotification);
```

### Filtraggio

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

// mantiene solo gli utenti per cui isActive() restituisce true
// equivalente a $users->filter(fn ($user) => $user->isActive())

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

### Aggregazioni

```php theme={null}
// somma sulla proprietà post_count di ogni utente
$totalPosts = $users->sum->post_count;

// massimo sullo score di ogni utente
$highestScore = $users->max->score;

// media sull'age di ogni utente
$averageAge = $users->avg->age;
```

### Raggruppamento e ordinamento

```php theme={null}
// raggruppa per proprietà role
$grouped = $users->groupBy->role;

// ordinamento crescente per proprietà name
$sorted = $users->sortBy->name;

// ordinamento decrescente per proprietà created_at
$sorted = $users->sortByDesc->created_at;
```

### Appiattire l'annidamento con flatMap

```php theme={null}
// espande le relazioni posts di ogni utente in un'unica collection
$posts = $users->flatMap->posts;
```

### Verifiche condizionali

```php theme={null}
// verifica che tutti siano admin
$allAdmins = $users->every->isAdmin();

// verifica che almeno uno sia attivo
$hasActive = $users->contains->isActive();

// verifica che tutti abbiano un piano specifico
$allPro = $users->every->hasPlan('pro');
```

### Collection di stringhe

Funziona anche con collection di stringhe. `__call()` del proxy, in caso di stringa, invoca il metodo come statico.

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

// per collection di stringhe la closure è più esplicita
$upper = $names->map(fn ($name) => strtoupper($name));
// ['ALICE', 'BOB', 'CHARLIE']
```

<Info>
  Perché gli higher-order messages funzionino con collection di stringhe, il metodo deve essere definito staticamente sul tipo stringa. Di solito sono più naturali con collection di modelli Eloquent o classi personalizzate.
</Info>

## Confronto con le normali closure

Gli higher-order messages sono concisi, ma non applicabili in ogni caso.

```php theme={null}
// higher-order messages: ideali per semplici accessi a proprietà o chiamate a metodo
$emails = $users->map->email;
$users->each->sendWelcomeMail();
$admins = $users->filter->isAdmin();

// closure: adatte a logica complessa o quando servono argomenti
$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>
  Se stai "estraendo la stessa proprietà da ogni elemento" o "chiamando lo stesso metodo su ogni elemento", gli higher-order messages sono più leggibili. Se la condizione è complessa o gli argomenti sono dinamici, usa una closure.
</Tip>

## Usare gli higher-order messages in classi personalizzate

Per sfruttare il meccanismo di `HigherOrderCollectionProxy` tramite il trait `EnumeratesValues`, chiami `Collection::proxy()` per aggiungere il metodo tra quelli proxificabili.

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

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

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // aggiungi una macro personalizzata tra i target proxy
        Collection::macro('active', function () {
            return $this->filter(fn ($item) => $item->isActive());
        });

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

```php theme={null}
// dopo la registrazione è utilizzabile come higher-order message
$activeUsers = $users->active;
```

## Prossimi passi

<Card title="Trait Conditionable" icon="git-branch" href="/it/advanced/conditionable">
  Impara l'implementazione interna di `when()` / `unless()` e come applicarlo al QueryBuilder e alle tue classi.
</Card>


## Related topics

- [Collection Deep Dive](/it/advanced/collection-deep-dive.md)
- [Trait Conditionable](/it/advanced/conditionable.md)
- [Guida all'aggiornamento da Laravel 12 a 13](/it/blog/upgrade-12-to-13.md)
- [Helper tap() e trait Tappable](/it/advanced/tap.md)
- [Trait Macroable](/it/advanced/macroable.md)
