Ich habe einige PHP 5.3.0
Funktionen überprüft und bin auf der Website auf Code gestoßen, der ziemlich lustig aussieht:
public function getTotal($tax)
{
$total = 0.00;
$callback =
/* This line here: */
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
als eines der Beispiele für anonyme Funktionen .
Weiß jemand davon? Irgendeine Dokumentation? Und es sieht böse aus, sollte es jemals benutzt werden?
use
Schlüsselwort wird auch zum Aliasing von Namespaces verwendet . Es ist erstaunlich, dass die Syntax mehr als 3 Jahre nach der Veröffentlichung von PHP 5.3.0function ... use
immer noch offiziell undokumentiert ist, was Schließungen zu einer undokumentierten Funktion macht. Das Dokument verwirrt sogar anonyme Funktionen und Schließungen . Die einzige (Beta und inoffizielle) Dokumentation, dieuse ()
ich auf php.net finden konnte, war der RFC für Schließungen .use
wird auch zum Einfügen einestrait
in einclass
!Eine einfachere Antwort.
function ($quantity) use ($tax, &$total) { .. };
$tax
innerhalb des Verschlusses hat also keine externen Auswirkungen, es sei denn, es ist ein Zeiger, wie es ein Objekt ist.&$total
. Auf diese Weise$total
ändert sich der Wert der ursprünglichen Variablen, wenn der Wert von DOES HAVE einen externen Effekt ändert.Wie @Mytskine hervorhob , ist der RFC für Schließungen wahrscheinlich die beste ausführliche Erklärung . (Stimmen Sie ihn dafür ab.)
quelle
$closure = function ($value) use ($localVar as $alias) { //stuff};
Fehler ist:Parse: syntax error, unexpected 'as' (T_AS), expecting ',' or ')'
&$total
auch einen internen Effekt hat. Mit anderen Worten, wenn Sie den Wert$total
außerhalb des Abschlusses nach seiner Definition ändern , wird der neue Wert nur übergeben, wenn es sich um einen Zeiger handelt.global
nur der Zugriff auf den globalen Namespace möglich ist, währenduse
der Zugriff auf Variablen im übergeordneten Namespace möglich ist. Globale Variablen werden im Allgemeinen als böse angesehen. Der Zugriff auf den übergeordneten Bereich ist häufig der eigentliche Zweck der Erstellung eines Abschlusses. Es ist nicht "böse", da sein Umfang sehr begrenzt ist. Andere Sprachen wie JS implizit verwenden die Variablen des übergeordneten Bereichs (als Zeiger, nicht als Wert kopiert).You can pass in variables as pointers like in case of &$total. This way, modifying the value of $total DOES HAVE an external effect, the original variable's value changes.
Das
function () use () {}
ist wie ein Abschluss für PHP.Ohne
use
kann die Funktion nicht auf die übergeordnete Bereichsvariable zugreifenDer
use
Wert der Variablen stammt vom Zeitpunkt der Definition der Funktion und nicht vom Zeitpunkt des Aufrufsuse
variable Referenz mit&
quelle
Verschlüsse sind wunderschön! Sie lösen viele Probleme, die mit anonymen Funktionen einhergehen, und ermöglichen wirklich eleganten Code (zumindest solange wir über PHP sprechen).
Javascript-Programmierer verwenden ständig Closures, manchmal sogar ohne es zu wissen, da gebundene Variablen nicht explizit definiert sind - dafür ist "use" in PHP gedacht.
Es gibt bessere Beispiele aus der Praxis als die oben genannten. Angenommen, Sie müssen ein mehrdimensionales Array nach einem Unterwert sortieren, aber der Schlüssel ändert sich.
Warnung: ungetesteter Code (ich habe php5.3 atm nicht installiert), aber es sollte ungefähr so aussehen.
Es gibt einen Nachteil: Viele PHP-Entwickler sind möglicherweise etwas hilflos, wenn Sie sie mit Schließungen konfrontieren.
Um die Schönheit von Verschlüssen besser zu verstehen, gebe ich Ihnen ein weiteres Beispiel - diesmal in Javascript. Eines der Probleme ist das Scoping und die dem Browser innewohnende Asynchronität. vor allem, wenn es um
window.setTimeout();
(oder -intervall) geht. Sie übergeben also eine Funktion an setTimeout, können jedoch keine Parameter angeben, da die Bereitstellung von Parametern den Code ausführt!myFunction gibt eine Funktion mit einer Art vordefiniertem Parameter zurück!
um ehrlich zu sein, ich mag PHP seit 5.3 und anonymen Funktionen / Schließungen viel mehr. Namespaces mögen wichtiger sein, aber sie sind viel weniger sexy .
quelle
Zupa hat großartige Arbeit geleistet, um Abschlüsse mit 'use' und den Unterschied zwischen EarlyBinding und Referencing der Variablen, die 'used' sind, zu erklären.
Also habe ich ein Codebeispiel mit frühem Binden einer Variablen gemacht (= Kopieren):
Beispiel mit Referenzierung einer Variablen (beachten Sie das Zeichen '&' vor der Variablen);
quelle
Bis in die letzten Jahre hat PHP seinen AST definiert und der PHP-Interpreter hat den Parser vom Evaluierungsteil isoliert. Während der Zeit, in der der Abschluss eingeführt wird, ist der Parser von PHP stark an die Auswertung gekoppelt.
Daher hat der Interpreter bei der ersten Einführung des Abschlusses in PHP keine Methode, um zu wissen, welche Variablen im Abschluss verwendet werden, da er noch nicht analysiert wurde. Daher muss der Benutzer die Zend-Engine durch expliziten Import erfreuen und die Hausaufgaben machen, die Zend machen sollte.
Dies ist der sogenannte einfache Weg in PHP.
quelle