Lambdas (also anonyme Funktionen) wurden in PHP mit Version 5.3 eingeführt und helfen dabei Funktionen, die nur an einer einzigen Stelle verwendet werden, vom globalen Scope fern zu halten. Ein Closure wiederum ist eine spezielle Art von Lambda. In diesem Beitrag erkläre ich euch wie beides definiert und verwendet wird.
Definition einer anonymen Funktion
Eine anonyme Funktion hat keinen Namen. Ansonsten gibt es keine Unterschiede zur „normalen“ Funktion.
1 2 3 |
function () { echo 'Ich bin so anonym!'; } |
Da wir sie so aber nicht aufrufen können, muss sie einer Variablen zugewiesen werden.
1 2 3 4 5 6 |
$dieFunktion = function () { echo 'Ich bin so anonym!'; }; // Können wir dann so aufrufen. $dieFunktion(); |
Wer sich dabei nach dem Sinn fragt, hat den richtigen Riecher: Das wirst du im echten Leben wohl kaum so machen.
Die wahre Bedeutung erschließt sich, wenn wir die anonyme Funktion direkt als Argument (meist dann als Callback verwendet) übergeben.
1 2 3 4 5 6 7 |
function echoText(callable $callback) { echo $callback(); } echoText(function () { return 'Ich bin so anonym!'; }); |
Was ist jetzt ein Closure in PHP?
Ein Lambda wird zum Closure, wenn es Zugang zu Variablen bekommt, die innerhalb der Funktion normalerweise nicht zur Verfügung stehen würden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function echoText(callable $callback) { echo $callback(), "\n"; } function funktionMitVariable() { // $name ist normalerweise nur in dieser Funktion verfügbar $name = 'Stefan'; echoText(function () use ($name) { // Durch use wird $name hier ebenfalls verfügbar, auch für den Fall, // dass die äußere Funktion schon terminiert ist. return 'Name: '.$name; }); } funktionMitVariable(); |
Stolperfalle beim Closure
Aber Achtung, das Closure hat keinen Einfluss auf die übergebene Variable, es wird nur der Wert beim Aufruf kopiert.
1 2 3 4 5 6 7 8 9 10 11 12 |
$count = 0; $increase = function () use ($count) { $count++; echo $count; }; echo $count; // 0 $increase(); // 1 echo $count; // 0 |
Wollen wir das wirklich, müssen wir die Variable als Referenz übergeben.
1 2 3 4 5 6 7 8 9 10 11 12 |
$count = 0; $increase = function () use (&$count) { $count++; echo $count; }; echo $count; // 0 $increase(); // 1 echo $count; // 1 |
Können auch Parameter übergeben werden?
Klar! Lambdas sind auch nur Funktionen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$arr = ['a', 'b', 'c']; array_walk($arr, function(&$value, $index, $prepend) { $value = $prepend.$value; }, 'foo'); print_r($arr); /* Array ( [0] => fooa [1] => foob [2] => fooc ) */ |
Fazit
Lambdas und in der Erweiterung Closures helfen uns dabei Funktionen, die ohnehin nur einmal verwendet werden sollen, direkt an Ort und Stelle zu definieren.