Closures sind ein zentrales Konzept in PHP. Eine Closure ist eine anonyme Funktion, die auf Variablen aus ihrem umgebenden Gültigkeitsbereich (Scope) zugreifen kann. Sie werden in Variablen gespeichert, als Parameter übergeben und als Rückgabewerte verwendet. Closures kommen in nahezu jedem modernen PHP-Projekt zum Einsatz, sei es in Array-Funktionen wie array_filter(), als Callbacks in Frameworks oder als Event-Handler. In diesem Tutorial lernst du die Syntax, das use-Keyword und den Unterschied zu Arrow Functions.

Bevor es an Praxisbeispiele geht, wird zunächst erklärt, was eine Closure genau ist und wie sie sich von einer gewöhnlichen Funktion unterscheidet.
Was ist eine Closure?
Eine Closure ist eine Funktion ohne Namen, die Variablen aus dem umgebenden Scope einfangen kann. Technisch gesehen sind alle anonymen Funktionen in PHP Instanzen der internen Closure-Klasse. Der Begriff Closure betont dabei die Fähigkeit, Variablen einzuschließen (to close over). Closures wurden in PHP 5.3 eingeführt und sind seitdem ein fester Bestandteil der Sprache. Vor ihrer Einführung mussten Callback-Funktionen in PHP als benannte Funktionen oder als String mit dem Funktionsnamen definiert werden, was deutlich weniger flexibel war.
Anonyme Funktionen in PHP
Eine anonyme Funktion wird wie eine normale Funktion definiert, jedoch ohne Namen. Sie wird einer Variable zugewiesen und kann über diese Variable aufgerufen werden.
<?php
$begruessung = function(string $name): string {
return 'Hallo, ' . $name . '!';
};
echo $begruessung('Welt');
/* Ausgabe: Hallo, Welt! */
Wichtig ist das Semikolon nach der schließenden Klammer. Da die Funktion einer Variable zugewiesen wird, handelt es sich um eine Anweisung, die mit einem Semikolon abgeschlossen werden muss.
Variablen mit use einschließen
In PHP haben anonyme Funktionen keinen automatischen Zugriff auf Variablen aus dem umgebenden Scope. Das unterscheidet sie von Closures in JavaScript, wo der Zugriff auf den äußeren Scope automatisch geschieht. In PHP muss das use-Keyword verwendet werden, um Variablen explizit einzuschließen.
Übernahme by Value
Standardmäßig werden Variablen per Wert übernommen. Die Closure erhält eine Kopie der Variable zum Zeitpunkt der Definition, nicht beim Aufruf.
<?php
$prefix = 'Herr';
$anrede = function(string $name) use ($prefix): string {
return $prefix . ' ' . $name;
};
echo $anrede('Mueller');
/* Ausgabe: Herr Mueller */
/* $prefix aendern hat keinen Effekt (by value) */
$prefix = 'Frau';
echo $anrede('Mueller');
/* Ausgabe: Herr Mueller */
Obwohl $prefix nach der Definition der Closure auf 'Frau' geändert wurde, gibt die Closure weiterhin 'Herr Mueller' aus. Die Variable wurde zum Zeitpunkt der Definition kopiert.
Übernahme by Reference
Mit dem Referenzoperator & wird statt einer Kopie eine Referenz auf die Original-Variable übernommen. Änderungen an der Variable wirken sich dann auch innerhalb der Closure aus, und umgekehrt.
<?php
$zaehler = 0;
$erhoehen = function() use (&$zaehler): void {
$zaehler++;
};
$erhoehen();
$erhoehen();
echo $zaehler;
/* Ausgabe: 2 */
Die Closure verändert die Original-Variable $zaehler, weil sie per Referenz übernommen wurde. Dieses Muster eignet sich für Zähler, Akkumulatoren oder wenn die Closure einen Zustand zwischen Aufrufen beibehalten soll. Es sollte jedoch sparsam eingesetzt werden, da es den Code schwerer nachvollziehbar macht. Die Modifikation von Variablen über Referenzen ist ein Seiteneffekt, der bei der Fehlersuche übersehen werden kann. In den meisten Fällen ist die Übernahme by Value die sicherere und vorhersehbarere Variante.
Closures als Callbacks
Closures werden häufig als Callbacks an Funktionen übergeben. Das ist einer ihrer wichtigsten Einsatzbereiche. Viele eingebaute PHP-Funktionen akzeptieren einen callable-Parameter, der mit einer Closure belegt werden kann.
<?php
$zahlen = [1, 2, 3, 4, 5, 6, 7, 8];
$mindestwert = 5;
$gefiltert = array_filter(
$zahlen,
function(int $zahl) use ($mindestwert): bool {
return $zahl >= $mindestwert;
}
);
print_r($gefiltert);
/* Array ( [4] => 5 [5] => 6 [6] => 7 [7] => 8 ) */
Die Closure wird für jedes Element des Arrays aufgerufen und entscheidet, ob es beibehalten wird. Durch use ($mindestwert) hat die Closure Zugriff auf die Variable aus dem äußeren Scope.
Closures in Array-Funktionen
Neben array_filter() akzeptieren auch array_map(), usort(), array_walk() und viele weitere Array-Funktionen Closures als Callback. Hier ein Beispiel mit usort() für eine benutzerdefinierte Sortierung:
<?php
$produkte = [
['name' => 'Tastatur', 'preis' => 49.90],
['name' => 'Maus', 'preis' => 29.90],
['name' => 'Monitor', 'preis' => 299.00],
];
usort($produkte, function(array $a, array $b): int {
return $a['preis'] <=> $b['preis'];
});
/* Sortiert nach Preis aufsteigend */
Der Spaceship-Operator (<=>) gibt -1, 0 oder 1 zurück und eignet sich perfekt für Vergleichsfunktionen.
Die Closure-Klasse
Alle anonymen Funktionen in PHP sind Instanzen der internen Closure-Klasse. Das bedeutet, dass $fn instanceof Closure für jede anonyme Funktion true zurückgibt. Die Closure-Klasse stellt zusätzlich die Methoden bind() und bindTo() bereit, mit denen der $this-Kontext einer Closure nachträglich geändert werden kann.
Der Type-Hint Closure ist enger als callable, da callable auch Strings mit Funktionsnamen und Arrays mit Klasse und Methode akzeptiert. In modernem Code wird Closure bevorzugt, wenn sichergestellt werden soll, dass nur eine anonyme Funktion übergeben wird.
Die Methode Closure::fromCallable() wandelt jeden callable-Wert in eine Closure um. Seit PHP 8.1 gibt es dafür die kompaktere First-Class Callable Syntax: strlen(...) erzeugt eine Closure aus der eingebauten Funktion strlen. Dieses Muster wird häufig in Frameworks verwendet, um Callbacks einheitlich als Closures zu behandeln.
<?php
/* First-Class Callable Syntax (ab PHP 8.1) */
$laenge = strlen(...);
echo $laenge('Hallo');
/* Ausgabe: 5 */
/* Aeltere Variante */
$laenge = Closure::fromCallable('strlen');
Closures sind auch in modernen Frameworks wie Laravel allgegenwärtig. Route-Definitionen, Middleware, Event-Listener und Collection-Methoden arbeiten alle mit Closures. Das Verständnis von Closures ist deshalb eine Voraussetzung für die Arbeit mit diesen Frameworks.
Closure vs. Arrow Function
Seit PHP 7.4 gibt es Arrow Functions als kompaktere Alternative zu Closures. Arrow Functions verwenden die fn-Syntax, haben ein implizites return und übernehmen Variablen aus dem äußeren Scope automatisch per Wert, ohne use.
<?php
$faktor = 3;
/* Closure mit use */
$multipliziere = function(int $x) use ($faktor): int {
return $x * $faktor;
};
/* Arrow Function (kompakter, automatisches use) */
$multipliziere = fn(int $x): int => $x * $faktor;
echo $multipliziere(5);
/* Ausgabe: 15 */
Arrow Functions eignen sich für kurze, einzeilige Ausdrücke. Für mehrzeilige Logik, use by Reference oder komplexere Operationen bleiben klassische Closures die richtige Wahl. Beide Varianten sind Instanzen der Closure-Klasse und können überall dort verwendet werden, wo ein callable oder Closure Type-Hint erwartet wird.
Closures und $this
Closures, die innerhalb einer Objektmethode definiert werden, binden ab PHP 5.4 automatisch $this. Dadurch hat die Closure Zugriff auf die Eigenschaften und Methoden des aktuellen Objekts.
<?php
class Warenkorb
{
private array $artikel = [];
public function hinzufuegen(string $name): void
{
$this->artikel[] = $name;
}
public function anzeigen(): Closure
{
return function(): string {
return implode(', ', $this->artikel);
};
}
}
$korb = new Warenkorb();
$korb->hinzufuegen('PHP-Buch');
$korb->hinzufuegen('Kaffeetasse');
$zeige = $korb->anzeigen();
echo $zeige();
/* Ausgabe: PHP-Buch, Kaffeetasse */
Die Closure hat Zugriff auf $this->artikel, obwohl die Eigenschaft private ist. Das liegt daran, dass die Closure den Kontext des Objekts übernimmt.
flowchart TD
A["Parent Scope"] -->|"use ($prefix)"| B["Closure"]
F["array_filter()"] -->|"Callback"| B
B --> C["Zugriff auf $prefix"]
B --> D["Eigene Parameter"]
B --> E["Eigene Logik"]
Typische Fehler und Stolperfallen
Beim Arbeiten mit Closures gibt es einige häufige Fehlerquellen:
- Ohne
use sind Variablen aus dem äußeren Scope in der Closure nicht verfügbar. Das ist ein fundamentaler Unterschied zu JavaScript, wo der Zugriff automatisch geschieht. use by Value kopiert den Wert zum Zeitpunkt der Definition. Änderungen an der Variable nach der Definition wirken sich nicht auf die Closure aus. - Das Semikolon nach der schließenden Klammer der Closure-Zuweisung wird oft vergessen. PHP wirft dann einen Syntax Error.
- Closures innerhalb von Objektmethoden binden automatisch
$this. Das kann zu unerwartetem Verhalten führen, wenn die Closure außerhalb des Objektkontexts verwendet wird. - Die Verwechslung von
callable und Closure als Type-Hint. callable ist breiter und akzeptiert auch andere aufrufbare Konstrukte.
Fazit
Closures sind ein mächtiges Werkzeug in PHP, das anonyme Funktionen mit dem Zugriff auf den umgebenden Scope verbindet. Durch das use-Keyword lassen sich Variablen gezielt by Value oder by Reference einschließen. Als Callbacks in Array-Funktionen, Event-Handlern und Frameworks sind Closures allgegenwärtig. Arrow Functions bieten seit PHP 7.4 eine kompaktere Alternative für einfache Ausdrücke, ersetzen aber nicht alle Einsatzbereiche klassischer Closures. Wer Closures beherrscht, versteht ein Kernkonzept moderner PHP-Entwicklung und kann die Funktionsweise von Frameworks wie Laravel und Symfony besser nachvollziehen, die Closures intensiv für Routing, Middleware und Collection-Methoden einsetzen.