First-Class-Callable-Syntax in PHP: aus strlen(...) wird ein echter Wert
Funktionen als Zeichenketten weiterzureichen – 'strlen', [$objekt, 'methode'] – hat nie jemand gemocht: kein Tippfehlerschutz, keine Sprungmarke in der IDE. Seit PHP 8.1 schreibst du drei Punkte und bekommst ein Closure-Objekt.
PHP kennt seit jeher „Callables", also Funktionen, die man irgendwohin weiterreicht. Nur sah das lange so aus:
$sauber = array_map('trim', $namen); // Funktion als Zeichenkette
$brutto = array_map([$preis, 'mitSteuer'], $netto); // Methode als ArrayBeides funktioniert – und beides ist eine Zeichenkette, die niemand prüft. Vertippst du dich, merkst du es zur Laufzeit. Deine IDE springt nicht zur Definition, die Umbenennen-Funktion übersieht die Stelle, und statische Analyse zuckt mit den Schultern.
Seit PHP 8.1 gibt es dafür eine eigene Schreibweise: den Namen aufrufen, aber statt der Argumente drei Punkte setzen.
So sieht das aus
<?php
$namen = [' Anna ', 'Bert', ' Cem '];
// Funktion:
$sauber = array_map(trim(...), $namen);
// ['Anna', 'Bert', 'Cem']
// Methode eines Objekts:
class Preis {
public function __construct(private float $satz) {}
public function mitSteuer(float $netto): float {
return round($netto * (1 + $this->satz), 2);
}
}
$p = new Preis(0.19);
$brutto = array_map($p->mitSteuer(...), [10.0, 99.99]);
// [11.9, 118.99]
// Statische Methode:
$ids = array_map(Nutzer::idVon(...), $nutzer);
// Und man kann es auch einfach hinlegen:
$laenge = strlen(...);
var_dump($laenge instanceof Closure); // bool(true)
echo $laenge('Hallo'); // 5Die drei Punkte sind kein Platzhalter für Argumente – sie sind die komplette Schreibweise. trim(...) ruft trim nicht auf, sondern erzeugt ein Closure-Objekt, das den Aufruf später erledigt. Das ist derselbe Effekt wie Closure::fromCallable('trim'), nur kürzer und vom Compiler geprüft.
Warum das mehr ist als Kosmetik
Der Name wird beim Kompilieren aufgelöst. Eine Funktion, die es nicht gibt, fällt sofort auf – nicht erst, wenn der Code das erste Mal durchlaufen wird. Bei einer Zeichenkette merkt es niemand, bis ein Nutzer darauf tritt.
$this wird mitgenommen. $p->mitSteuer(...) bindet das Objekt fest ein. Bei der Array-Schreibweise musste man selbst darauf achten, dass das Objekt zum Zeitpunkt des Aufrufs noch existiert.
Private Methoden gehen auch – wenn du die Schreibweise innerhalb der Klasse benutzt. array_map($this->pruefe(...), $zeilen) funktioniert, [$this, 'pruefe'] von außen nicht.
Zwei Stolpersteine
Es sind wirklich nur drei Punkte, sonst nichts. strlen(..., 5) oder trim(..., ' ') sind Syntaxfehler. Willst du ein Argument vorbelegen, brauchst du weiterhin eine kurze Pfeilfunktion: fn($s) => trim($s, '/').
Sprachkonstrukte sind keine Funktionen. isset(...), empty(...), echo(...) gibt es nicht – die sehen nur aus wie Funktionen. array_map(strlen(...), $x) geht, array_map(empty(...), $x) nicht.
Wo es sich lohnt
Am meisten dort, wo eine Liste durch eine Kette von Verarbeitungsschritten läuft: array_map, array_filter, usort, array_walk. Statt Zeichenketten stehen dort echte Namen, und ein usort($namen, strcmp(...)) liest sich endlich wie das, was es tut.
Ich nutze das im eigenen CMS hinter bymw.de überall da, wo früher Callables als Text herumlagen – gefunden habe ich beim Umstellen prompt zwei Stellen mit einem Tippfehler, die nur deshalb nie aufgefallen waren, weil der Zweig selten lief. Genau dafür ist die Schreibweise da.
Voraussetzung ist PHP 8.1 oder neuer. Läuft dein Hosting noch auf 8.0, bleibt es bei der alten Schreibweise – oder du hebst die Version an, es lohnt sich ohnehin.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
array_find, array_any und array_all in PHP 8.4 – Arrays durchsuchen ohne Schleife
„Gibt es einen inaktiven Eintrag?", „Sind alle bezahlt?", „Hol mir den ersten Treffer" – dafür hast du bisher eine foreach-Schleife mit break geschrieben. PHP 8.4 macht daraus je eine Zeile, die genau sagt, was sie meint.
Schöne Zeilenumbrüche in CSS – text-wrap balance und pretty
Eine Überschrift, bei der ein einzelnes Wort einsam in der letzten Zeile hängt, sieht unruhig aus. Mit text-wrap balance und pretty überlässt du dem Browser das saubere Umbrechen – ohne manuelle <br> und ohne JavaScript.
@layer in CSS: Kaskadenebenen statt !important-Wettrüsten
Irgendwann steht in jedem gewachsenen Stylesheet das erste !important – und ein halbes Jahr später das dreißigste. Mit @layer legst du die Reihenfolge einmal fest, und ab da gewinnt nicht mehr der längste Selektor, sondern die Ebene, die du bestimmt hast.