Higher-Order Messages sind eine Syntax, mit der Sie Collection-Methoden wie einen Property-Zugriff aufrufen. Ohne einen Callback zu schreiben, können Sie für jedes Element eine Methode aufrufen oder eine Property abfragen.
Wenn Sie wie in $collection->map als Property zugreifen, wird __get() des Traits EnumeratesValues aufgerufen.
// src/Illuminate/Collections/Traits/EnumeratesValues.phppublic 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);}
Ist der Methodenname in $proxies enthalten, wird eine Instanz von HigherOrderCollectionProxy zurückgegeben. Dieser Proxy hält die Collection und den Methodennamen fest.
Higher-Order Messages sind bei Eloquent-Collections besonders praktisch.
$users = User::with('posts')->get();// Methodenaufruf: Status jedes Nutzers aktualisieren$users->each->markAsVerified();// Property-Zugriff: nur Namen entnehmen$names = $users->map->name;// Argument an die Methode übergeben$users->each->sendPasswordReset('ja');// E-Mails versenden$users->each->notify(new WelcomeNotification);
// Summe über die Property post_count jedes Nutzers$totalPosts = $users->sum->post_count;// Maximum der Property score jedes Nutzers$highestScore = $users->max->score;// Durchschnitt der Property age jedes Nutzers$averageAge = $users->avg->age;
// Nach der Property role gruppieren$grouped = $users->groupBy->role;// Aufsteigend nach der Property name sortieren$sorted = $users->sortBy->name;// Absteigend nach der Property created_at sortieren$sorted = $users->sortByDesc->created_at;
// Sind alle Administratoren?$allAdmins = $users->every->isAdmin();// Gibt es mindestens einen aktiven Nutzer?$hasActive = $users->contains->isActive();// Haben alle einen bestimmten Plan?$allPro = $users->every->hasPlan('pro');
Auch bei Collections aus Strings können Sie sie nutzen. Der __call()-Proxy ruft die Methode bei Strings als statische Methode auf.
$names = collect(['alice', 'bob', 'charlie']);// Bei String-Collections ist eine Closure explizit$upper = $names->map(fn ($name) => strtoupper($name));// ['ALICE', 'BOB', 'CHARLIE']
Für Higher-Order Messages auf String-Collections muss die Methode statisch für den String-Typ definiert sein. Natürlicher ist der Einsatz bei Collections von Eloquent-Modellen oder eigenen Klassen.
Higher-Order Messages sind kompakt, decken aber nicht jede Situation ab.
// Higher-Order Message: gut für schlichte Property-Abfragen oder Methodenaufrufe$emails = $users->map->email;$users->each->sendWelcomeMail();$admins = $users->filter->isAdmin();// Closure: passend bei komplexer Logik oder Argumenten$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;});
Wenn Sie „die gleiche Property aus jedem Element ziehen” oder „die gleiche Methode auf jedem Element aufrufen”, ist eine Higher-Order Message besser lesbar. Bei komplexen Bedingungen oder dynamischen Argumenten greifen Sie zur Closure.
Higher-Order Messages in eigenen Klassen einsetzen
Um den Mechanismus von HigherOrderCollectionProxy über den Trait EnumeratesValues zu nutzen, registrieren Sie Methoden per Collection::proxy() als Proxy-Ziele.
namespace App\Providers;use Illuminate\Support\Collection;use Illuminate\Support\ServiceProvider;class AppServiceProvider extends ServiceProvider{ public function boot(): void { // Eigenes Macro als Proxy-Ziel registrieren Collection::macro('active', function () { return $this->filter(fn ($item) => $item->isActive()); }); Collection::proxy('active'); }}
// Nach der Registrierung als Higher-Order Message verwendbar$activeUsers = $users->active;