PHP 5.3: Closures

von Jan Pieper | 2 | 8 Kommentare | 5324 Aufrufe

Anzeige Hier werben

Nach Sprachen wie LUA, Python, Javascript etc. wird es ab der Version 5.3 auch in PHP möglich sein, Funktionen mit einem Zustand zu deklarieren. Dafür können der Funktion, bei ihrer Deklaration, Variablen, aus dem aktuellen Gültigkeitsbereich, zugewiesen werden. In Klassenmethoden wird einer Lambda Funktion die Variable $this implizit (automatisch) zugewiesen.

Einfaches Beispiel  
PHP
1
2
3
4
5
6
7
8
9
<?php

$x = 12;
$closure = function($a) use ($x) {
    return $x - $a;
};
$closure(4); // int(8)

?>

Der Lamda Funktion wird in diesem Beispiel, bei ihrer Deklaration, die Variable $x übergeben. Diese Variable ist der Funktion so lange bekannt, wie die Funktion selbst existiert. In use(...) können mehrere Variablen kommasepariert eingetragen werden.

Closures werden z.B. für Callbacks gebraucht, da man z.B. zum Zeitpunkt, an dem die Funktion als Callback aufgerufen wird, den Zustand benötigt, wie er war, als die Funktion deklariert wurde, und nicht, wie er aktuell (vllt. 100 Zeilen später) ist. Zwischen Deklaration und Aufruf der Funktion kann nämlich so einiges passieren.

Beispiel  
PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

$status = 200;
$closure = function($result) use ($status) {
    return ($result == $status);
}

/* 100 Zeilen Code */

$status = 300;

/* 100 Zeilen Code */

$closure(200); // bool(true)
$closure(300); // bool(false)

?>

Hier kann man sehen, dass der Funktion zur Deklaration die Variable $status übergeben wird. Obwohl sich der Inhalt der Variable $status im weiteren Verlauf des Scripts ändert, weiß die Funktion immernoch, dass der Wert 200 war. Wenn man nun die Funktion mit dem Parameter 200 aufruft bekommt man den boolschen Wert true zurückgeliefert, da dieser gleich dem Inhalt der $status Variable zur Deklarationszeit ist.

Dem use(...) können auch Referenzen gegeben werden. In dem Fall hat die Variable in der Funktion beim Aufruf den Wert, den die Variable aktuell im Script hat. Also unbedingt nicht den Wert, den sie bei Deklaration der Funktion hatte.

Nutzung einer Referenz  
PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

$status = 200;
$closure = function($result) use (&$status) {
    return ($result == $status);
}

/* 100 Zeilen Code */

$status = 300;

/* 100 Zeilen Code */

$closure(200); // bool(false)
$closure(300); // bool(true)

?>

Nun ist der Wert der Variable $status, innerhalb der Funktion, nicht mehr 200 sondern 300, da der Inhalt sich im Ablauf des Skripts geändert hat.

Über den Autor: Jan Pieper
arbeitet bei der Adcloud GmbH als Software Engineer und beschäftigt sich bereits seit dem Jahr 2000 mit der Entwicklung von dynamischen Internetseiten.
Profilseite betrachten

Kommentare: PHP 5.3: Closures

Neuen Kommentar schreiben
Super! Habe ich auch bisher Vermisst.
Beantworten

Nachdem ich jetzt sher lang fast nur Javascript programmiert habe hab ich Closures und viele andere "Skriptsprachen-Standardkonstruktionen" sehr vermisst als ich jetzt für den FlashCounter mal wieder PHP Programmiert habe.

Thomas H am 12.01.2009 um 19:28
global
Beantworten

ist doch an sich nichts anderes, was global nicht auch tut, nur mit ein paar zeichen weniger, oder irre ich mich?

Holger V am 12.01.2009 um 18:32
Re: global
Beantworten

Mit global greifst du auf eine Variable zu, wie sie zum Zeitpunkt des Aufrufs der Funktion ist. Mit den Closures beinhalten die Variablen, die du per use (...) angibst, den Wert, den sie zur Zeit der Deklaration der Funktion haben. Das ist was anderes :-)

Jan Pieper am 12.01.2009 um 18:47
tippfehler?
Beantworten

erstmal vielen Dank, ist sehr schön erklärt :)

aber kann es sein dass sich im dritten Code-Beispiel ein Tippfehler eingeschlichen hat?

"Dem use(...) können auch Referenzen gegeben werden. In dem Fall hat die Variable in der Funktion beim Aufruf den Wert, den die Variable aktuell im Script hat. Also unbedingt nicht den Wert, den sie bei Deklaration der Funktion hatte."

$closure = function ( &$result ) use ( $status ) {

return( $result == $status );

}

Ist die Referenz in diesem fall nicht dem $status zuzuweisen?

$closure = function ( $result ) use ( &$status ) {

return( $result == $status );

}

hat sich die Funktionsweise von Referenzen in PHP 5 nicht auch geändert, bzw wurde nur noch als Überbleibsel aus PHP 3 und 4 "toleriert" und ist gleichwertig mit der entsprechenden Variablen? (Oder hab ich da irgendwo was falsch verstanden? :)

bartrail am 12.01.2009 um 12:53
Re: tippfehler?
Beantworten

Danke, war wirklich ein Tippfehler. Das & gehört ins use (...) zur $status-Variable. Ist korrigiert.

Jan Pieper am 12.01.2009 um 18:35
Re: tippfehler?
Beantworten

hat sich die Funktionsweise von Referenzen in PHP 5 nicht auch geändert, bzw wurde nur noch als Überbleibsel aus PHP 3 und 4 "toleriert" und ist gleichwertig mit der entsprechenden Variablen? (Oder hab ich da irgendwo was falsch verstanden? :)

Nein, nur bei Objekten, nicht allgemein.

David Danier am 12.01.2009 um 14:14
Re: tippfehler?
Beantworten

d.h. ich kann instanziierte objekte dereferenzieren aber nicht normale variablen?

bartrail am 12.01.2009 um 19:20
Re: tippfehler?
Beantworten

Bei Objekten hast du automatisch eine Referenz. Bei Variablen musst du es explizit sagen, dass du eine Referenz willst.

Jan Pieper am 12.01.2009 um 22:28