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

# Mensajes de orden superior en colecciones

> Cómo funcionan los mensajes de orden superior (Higher-order Messages) de las colecciones y cómo utilizarlos en la práctica.

## Qué son los mensajes de orden superior

Los mensajes de orden superior (Higher-order Messages) son una sintaxis para invocar métodos de una colección accediendo a ellos como si fueran propiedades. Sin escribir una callback, puedes llamar a un método o acceder a una propiedad de cada elemento.

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

// Forma con mensajes de orden superior
$names = $users->map->name;
```

`$users->map->name` significa «extrae la propiedad `name` de cada usuario y aplica `map`».

## Cómo funciona — HigherOrderCollectionProxy

Cuando accedes a algo como `$collection->map` como si fuera una propiedad, se invoca `__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);
}
```

Si el nombre está en `$proxies`, se devuelve una instancia de `HigherOrderCollectionProxy`. Este proxy conserva la colección y el nombre del método.

### Proxy de acceso a propiedad mediante \_\_get

Si a continuación accedes a una propiedad (`->name`), se invoca el `__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};
    });
}
```

Es decir, `$users->map->name` equivale a:

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

### Proxy de llamada a método mediante \_\_call

Si en su lugar llamas a un método (`->activate()`), se invoca el `__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()` equivale a:

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

## Lista de métodos compatibles

Los métodos disponibles como mensajes de orden superior se declaran en el 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',
];
```

Para añadir métodos personalizados, usa `Collection::proxy()`.

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

## Casos de uso prácticos

### Colecciones de modelos Eloquent

Los mensajes de orden superior son especialmente útiles con colecciones de Eloquent.

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

// Llamada a método: actualiza el estado de cada usuario
$users->each->markAsVerified();

// Acceso a propiedad: obtén solo los nombres
$names = $users->map->name;

// Con argumentos
$users->each->sendPasswordReset('es');

// Envío de notificación
$users->each->notify(new WelcomeNotification);
```

### Filtrado

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

// Deja solo los usuarios para los que isActive() devuelve true
// Equivale a $users->filter(fn ($user) => $user->isActive())

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

### Agregaciones

```php theme={null}
// Suma la propiedad post_count de cada usuario
$totalPosts = $users->sum->post_count;

// Máximo de la propiedad score
$highestScore = $users->max->score;

// Media de la propiedad age
$averageAge = $users->avg->age;
```

### Agrupación y ordenación

```php theme={null}
// Agrupar por la propiedad role
$grouped = $users->groupBy->role;

// Ordenar ascendentemente por la propiedad name
$sorted = $users->sortBy->name;

// Ordenar descendentemente por created_at
$sorted = $users->sortByDesc->created_at;
```

### Aplanar con flatMap

```php theme={null}
// Expande la relación posts de cada usuario en una única colección
$posts = $users->flatMap->posts;
```

### Comprobaciones condicionales

```php theme={null}
// Comprueba si todos son administradores
$allAdmins = $users->every->isAdmin();

// Comprueba si al menos uno está activo
$hasActive = $users->contains->isActive();

// Comprueba si todos tienen un plan concreto
$allPro = $users->every->hasPlan('pro');
```

### Colecciones de cadenas

También se pueden usar en colecciones de cadenas. El `__call()` del proxy trata las cadenas como si fueran una llamada estática.

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

// Para colecciones de cadenas suele ser más claro usar una closure
$upper = $names->map(fn ($name) => strtoupper($name));
// ['ALICE', 'BOB', 'CHARLIE']
```

<Info>
  Para usar mensajes de orden superior con una colección de cadenas, el método debe existir estáticamente en el tipo string. Normalmente, encajan mejor con colecciones de modelos Eloquent o clases propias.
</Info>

## Comparación con closures normales

Los mensajes de orden superior son concisos, pero no encajan en todos los casos.

```php theme={null}
// Mensaje de orden superior: adecuado para obtener propiedades o llamar a métodos simples
$emails = $users->map->email;
$users->each->sendWelcomeMail();
$admins = $users->filter->isAdmin();

// Closure: adecuada para lógica compleja o cuando se necesitan argumentos
$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>
  Cuando quieres «obtener la misma propiedad de cada elemento» o «llamar al mismo método en cada elemento», los mensajes de orden superior son más legibles. Si la condición es compleja o los argumentos son dinámicos, usa una closure.
</Tip>

## Usar mensajes de orden superior en clases propias

Para aprovechar el mecanismo de `HigherOrderCollectionProxy` a través del trait `EnumeratesValues`, llama a `Collection::proxy()` para añadir el método al conjunto de proxies.

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

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

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Añade una macro personalizada al conjunto de proxies
        Collection::macro('active', function () {
            return $this->filter(fn ($item) => $item->isActive());
        });

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

```php theme={null}
// Tras el registro, ya se puede usar como mensaje de orden superior
$activeUsers = $users->active;
```

## Próximos pasos

<Card title="Trait Conditionable" icon="git-branch" href="/es/advanced/conditionable">
  Aprende la implementación interna de `when()` / `unless()` y cómo aplicarla en QueryBuilder y clases propias.
</Card>


## Related topics

- [Collection Deep Dive](/es/advanced/collection-deep-dive.md)
- [Trait Conditionable](/es/advanced/conditionable.md)
- [Colecciones](/es/collections.md)
- [Laravel Prompts](/es/prompts.md)
- [Sesión](/es/session.md)
