42 Stimmen

Php Closures: Warum das 'static' in der anonymen Funktionserklärung, wenn es an eine statische Klasse gebunden wird?

Das Beispiel in der PHP-Dokumentation zu Closure::bind enthält static auf der anonymen Funktionsdeklaration. Warum? Ich kann keinen Unterschied finden, wenn es entfernt wird.

mit:

class A {
    private static $sfoo = 1;
}
$cl1 = static function() { // beachte das "static"
    return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // Ausgabe: 1

ohne:

class A {
    private static $sfoo = 1;
}
$cl1 = function() {
    return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // Ausgabe: 1

55voto

jlh Punkte 3672

Ich bin anderer Meinung. Es stimmt, dass es oft nicht wichtig ist. Aber manchmal ist es sehr wichtig.

Die Schließung, die eine Referenz auf $this hält, könnte das Garbage Collection dieses Objekts verhindern, was wiederum die Leistung signifikant beeinträchtigen könnte. Hier ist ein Beispiel, wo es wirklich einen großen Unterschied macht:

class LargeObject {
    protected $array;

    public function __construct() {
        $this->array = array_fill(0, 2000, 17);
    }

    public function getItemProcessor(): Closure {
        // Versuchen Sie es hier mit und ohne 'static'
        return static function () {
            // führen Sie eine Verarbeitung durch, die nichts mit $this zu tun hat
        };
    }
}

$start = microtime(true);

$processors = [];
for ($i = 0; $i < 2000; $i++) {
    $lo = new LargeObject();
    $processors[] = $lo->getItemProcessor();
}

$memory = memory_get_usage() >> 20;
$time = (microtime(true) - $start) * 1000;
printf("Das hat %dms gedauert und %dMB Speicher verbraucht\n", $time, $memory);

Hier ist die Ausgabe mit einer normalen Schließung:

Das hat 55ms gedauert und 134MB Speicher verbraucht

Hier ist die Ausgabe mit einer statischen Schließung:

Das hat 22ms gedauert und 1MB Speicher verbraucht

Ich habe dies mit PHP 7.3.19 auf Debian Buster getestet, also kann Ihre Erfahrung variieren. Offensichtlich ist dies ein speziell konstruiertes Beispiel, um den Unterschied zu demonstrieren. Aber solche Dinge können auch in echten Anwendungen passieren. Ich habe angefangen, Slevomats SlevomatCodingStandard.Functions.StaticClosure Sniff zu verwenden, um mich daran zu erinnern, immer statische Schließungen zu verwenden.

41voto

learning php Punkte 1144

Den Unterschied gefunden: Sie können statische Closures nicht an ein Objekt binden, sondern nur den Objektbereich ändern.

class foo { }

$cl = static function() { };

Closure::bind($cl, new foo); // PHP Warnung:  Kann keine Instanz an eine statische Closure binden
Closure::bind($cl, null, 'foo') // Sie können den Closure-Bereich ändern

21voto

Hendrik Rombach Punkte 320

Statische Closures, wie jeder andere statische Methode, können nicht auf $this zugreifen.

Wie jede andere Methode wird eine nicht-statische Closure, die nicht auf $this zugreift, in der Regel in einem statischen Kontext funktionieren.

8voto

Phil Punkte 140763

Wie Sie vielleicht bemerkt haben, spielt es keine Rolle.

Es ist ähnlich wie die Verwendung des static Schlüsselworts bei einer Klassenmethode. Du brauchst es nicht unbedingt, wenn du nicht $this innerhalb der Methode referenzierst (obwohl dies gegen strenge Standards verstößt).

Ich nehme an, PHP kann herausfinden, dass Sie die Closure meinen, um A statisch zuzugreifen, aufgrund des null 2. Arguments an bind()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X