Verwendung von "$ this" in einer anonymen Funktion in PHP vor 5.4.0

86

Das PHP-Handbuch besagt

Es ist nicht möglich, eine $thisanonyme Funktion vor PHP 5.4.0 zu verwenden

auf der Seite für anonyme Funktionen . Aber ich habe festgestellt, dass ich es zum Laufen bringen kann, indem ich es $thiseiner Variablen zuweise und die Variable an eine useAnweisung in der Funktionsdefinition übergebe.

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

Ist das eine gute Praxis?
Gibt es eine bessere Möglichkeit, $thismit PHP 5.3 auf eine anonyme Funktion zuzugreifen ?

dampfbetrieben
quelle
1
Nur eine kleine Forum-Konvention - normalerweise ist es besser, eine Antwort zu akzeptieren, als eine Frage zu bearbeiten, um Ihre bevorzugte Antwort widerzuspiegeln. Hauptsächlich deshalb, damit Antworten auf Dauer immer noch Sinn machen, aber natürlich auch, um eine korrekte Antwort zu würdigen.
Halfer
4
Passen Sie auf $CI = $this;und $CI =& $this; sind nicht wirklich identisch. Vielleicht für Ihre Zwecke, aber sie sind nicht gleich. Versuchen Sie es $CI = 'bla'; var_dump($this);mit beiden Versionen, um den Unterschied zu erkennen.
Rudie
1
@ Rudie Ich füge die Dokumentation für Ihren Kommentar hinzu
Steampowered
@steampowered Irgendwo online ist ein gutes Beispiel / ein guter Artikel darüber, aber ich konnte ihn nicht finden =) Entschuldigung. Probieren Sie es einfach aus, wenn Sie den Unterschied nicht sehen. Dann ist es offensichtlich.
Rudie

Antworten:

67

Es schlägt fehl, wenn Sie versuchen, eine geschützte oder private Methode darauf aufzurufen, da die Verwendung auf diese Weise als Aufruf von außen gilt. Soweit ich weiß, gibt es in 5.3 keine Möglichkeit, dies zu umgehen, aber mit PHP 5.4 wird es wie erwartet funktionieren:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}
$hello = new Hello();
$helloPrinter = $hello->createClosure();
$helloPrinter(); // outputs "Hello world"

Darüber hinaus können Sie für Anonymus-Funktionen (Closing Rebinding) ändern, auf was $ dies zur Laufzeit zeigt:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}

class Bye {

    private $message = "Bye world\n";

}

$hello = new Hello();
$helloPrinter = $hello->createClosure();

$bye = new Bye();
$byePrinter = $helloPrinter->bindTo($bye, $bye);
$byePrinter(); // outputs "Bye world"

Effektiv haben Anonymus-Funktionen eine bindTo () -Methode , bei der der erste Parameter verwendet werden kann, um anzugeben, auf was $ dies zeigt, und der zweite Parameter steuert, wie hoch die Sichtbarkeitsstufe sein soll . Wenn Sie den zweiten Parameter weglassen, entspricht die Sichtbarkeit dem Aufruf von "außen", z. Auf öffentliche Objekte kann nur zugegriffen werden. Beachten Sie auch die Funktionsweise von bindTo. Es ändert nicht die ursprüngliche Funktion, sondern gibt eine neue zurück .

K. Norbert
quelle
1
Markieren Sie Ihre Antwort richtig, aber nur zur Verdeutlichung für andere Leser: Die in der Frage verwendete Konvention funktioniert für öffentliche Methoden unter Verwendung des Objekts, auf das verwiesen wird $this.
Steampowered
5
Auf nicht öffentliche Methoden kann über Reflektion zugegriffen werden. Ineffizient und ein bisschen böse, aber es funktioniert.
Outis
7

Verlassen Sie sich nicht immer auf PHP, um Objekte als Referenz zu übergeben. Wenn Sie eine Referenz selbst zuweisen, ist das Verhalten nicht das gleiche wie in den meisten OO-Sprachen, in denen der ursprüngliche Zeiger geändert wird.

Ihr Beispiel:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

sollte sein:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

HINWEIS Die REFERENZ "&" und $ CI sollten zugewiesen werden, nachdem die letzten Aufrufe durchgeführt wurden. Andernfalls kann es sein, dass Sie in PHP nicht immer eine unvorhersehbare Ausgabe haben. Der Zugriff auf eine Referenz ist nicht immer dasselbe wie der Zugriff auf die ursprüngliche Klasse - wenn dies sinnvoll ist.

http://php.net/manual/en/language.references.pass.php

Christof Coetzee
quelle
6

Das ist die normale Art und Weise, wie es gemacht wurde.
Übrigens, versuchen Sie zu entfernen, dass &es ohne dies funktionieren sollte, da Objekte in irgendeiner Weise an ref vorbeigehen .

Itay Moav-Malimovka
quelle
1

Das scheint in Ordnung zu sein, wenn Sie als Referenz vorbeigehen, ist dies der richtige Weg, dies zu tun. Wenn Sie PHP 5 verwenden, benötigen Sie das &Symbol vorher nicht, $thisda es unabhängig davon immer als Referenz übergeben wird.

Feuer
quelle
2
Das OP muss 5.3 oder höher verwenden, da 4.x keine anonymen Funktionen unterstützt :-)
halfer
1

Das ist in Ordnung. Ich sollte denken, dass Sie dies auch tun könnten:

$CI = $this;

... da Zuordnungen mit Objekten immer Referenzen kopieren, nicht ganze Objekte.

halfer
quelle