PHP 5.3: Closures
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.
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.
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.
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.



Super! Habe ich auch bisher Vermisst.
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.
global
ist doch an sich nichts anderes, was global nicht auch tut, nur mit ein paar zeichen weniger, oder irre ich mich?
Re: global
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 :-)tippfehler?
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? :)
Re: tippfehler?
Danke, war wirklich ein Tippfehler. Das & gehört ins
use (...)zur$status-Variable. Ist korrigiert.Re: tippfehler?
Nein, nur bei Objekten, nicht allgemein.
Re: tippfehler?
d.h. ich kann instanziierte objekte dereferenzieren aber nicht normale variablen?
Re: tippfehler?
Bei Objekten hast du automatisch eine Referenz. Bei Variablen musst du es explizit sagen, dass du eine Referenz willst.