Ich habe auf SO und anderswo herumgelesen, aber ich kann anscheinend nichts Schlüssiges finden.
Gibt es eine Möglichkeit, Referenzen durch diese Aufrufliste effektiv zu tragen, was zu der gewünschten Funktionalität führt, wie im folgenden Beispiel beschrieben? Während das Beispiel nicht versucht, es zu lösen, veranschaulicht es sicherlich das Problem:
%Vor% Wenn wir nur auf call_user_func_array()
fokussieren, können wir feststellen, dass ( zumindest mit PHP 5.3.1 ) Argumente nicht implizit als Referenz übergeben werden können:
Durch explizites Übergeben des Array-Elements $test
als Referenz können wir dies lindern:
Wenn wir die Klasse mit __callStatic()
einführen, scheint ein expliziter Call-Time-Parameter durch Referenz ausgeführt zu werden, wie ich erwartet habe, aber Depreciation-Warnungen werden ausgegeben (in meiner IDE):
Das Auslassen des Referenzoperators in TestClass::testFunction()
führt dazu, dass $test
vom Wert an __callStatic()
übergeben wird, und wird natürlich als Arrayelement als Wert an testFunction()
via call_user_func_array()
übergeben. Dies führt zu einer Warnung, da testFunction()
eine Referenz erwartet.
Hacking herum, einige zusätzliche Details sind aufgetaucht. Die __callStatic()
-Definition hat, wenn sie durch Verweis zurückgegeben wird ( public static function &__callStatic()
), keinen sichtbaren Effekt. Außerdem können wir die Elemente des $arguments
-Arrays in __callStatic()
als Referenzen neu erstellen und sehen, dass call_user_func_array()
wie erwartet funktioniert:
Diese Ergebnisse werden erwartet, da $test
nicht mehr als Referenz übergeben wird. Die Änderung wird nicht in den Gültigkeitsbereich zurückgegeben. Dies bestätigt jedoch, dass call_user_func_array()
tatsächlich wie erwartet funktioniert und dass das Problem sicherlich auf die aufrufende Magie beschränkt ist.
Beim weiteren Lesen scheint es sich um einen "Bug" in der PHP-Behandlung von Benutzerfunktionen und um die __call()
/ __callStatic()
Magie handeln. Ich habe die Fehlerdatenbank nach vorhandenen oder verwandten Problemen durchgesehen und eine gefunden, konnte sie aber nicht erneut finden. Ich erwäge, einen weiteren Bericht oder eine Anfrage für das erneute Öffnen des vorhandenen Berichts zu veröffentlichen.
Das ist lustig.
%Vor%Dies funktioniert, aber es wird auch eine Call-Time-Pass-by-Reference-Warnung ausgelöst.
Das Hauptproblem ist, dass __callStatic
's zweites Argument wertmäßig ist. Es wird eine Kopie der Daten erstellt, es sei denn, diese Daten sind bereits eine Referenz.
Wir können den aufrufenden Fehler so duplizieren:
%Vor% Ich habe versucht, die Methode __callStatic
zu ändern, um das Array tief als Referenz zu kopieren, aber das hat auch nicht funktioniert.
Ich bin mir ziemlich sicher, dass die direkte Kopie, die von __callStatic
verursacht wird, hier ein Mörder sein wird, und dass ihr das nicht ohne genug Hoop Jumping tun könntest, um es ein wenig stickermäßig zu machen .
Ich beantworte das selbst mit einer Schritt-für-Schritt-Wiedergabe des Problems, die zeigt, dass es wahrscheinlich nicht möglich ist, die gewünschte Funktionalität zu erreichen.
Unsere Testfunktion ist ziemlich einfach und lautet wie folgt:
%Vor%Wenn wir die Funktion direkt aufrufen, verhält sie sich natürlich wie erwartet:
%Vor% Wenn wir die Funktion mit call_user_func_array
aufrufen:
Der Wert bleibt bei 1
, weil $value
nicht als Referenz übergeben wurde. Wir können das erzwingen:
Dies funktioniert wiederum als direkter Aufruf der Funktion.
Nun stellen wir die Klasse mit __callStatic
vor:
Wenn wir die Funktion aufrufen, indem wir sie durch __callStatic
:
Der Wert bleibt bei 1
, und wir erhalten auch eine Warnung:
Warning: Parameter 1 to testFunction() expected to be a reference, value given
Dies stellt sicher, dass $argumentArray
, das an __callStatic
übergeben wurde, keine Referenzen enthält. Das macht durchaus Sinn, da PHP nicht weiß, dass die Argumente durch Verweis in __callStatic
akzeptiert werden sollen oder dass wir die Argumente weiterleiten.
Wenn wir __callStatic
ändern, um das Array als Referenz zu akzeptieren, um das gewünschte Verhalten zu erzwingen:
Oh oh! Spaghetti-O's!
Fatal error: Method TestClass::__callstatic() cannot take arguments by reference
Kann das nicht tun; Außerdem wird trotzdem von der Dokumentation unterstützt :
Hinweis:
Keines der Argumente dieser magischen Methoden kann als Referenz weitergegeben werden.
Obwohl __callStatic
nicht als Referenz deklariert werden kann, wenn wir call_user_func_array
(, was in der Praxis ziemlich umständlich und selbstzerstörerisch wäre) verwenden würden, um Referenzen durch __callStatic
weiterzuleiten. :
Es funktioniert wieder.
Wow, nach mehr als einer Stunde, in der ich meine Gedanken durchbrenne, bin ich mir immer noch nicht sicher, aber ...
%Vor% Wenn wir einfache Logik (in dieser Situation) verwenden, wenn die Klasse die Funktion call_user_func_array()
aufruft, verwendet sie statische Strings als Parameter (übergeben von der magischen Methode __callStatic()
), also ist Parameter 2 eine Zeichenfolge in% call_user_func_array()
function und Dieser Parameter ist auch Parameter 1 für die Funktion testFunction()
. Es ist einfach String kein Zeiger auf Variable, und das ist wahrscheinlich ein Grund für eine Nachricht wie:
Mit anderen Worten, es kann der Variablen, die nicht vorhanden ist, keinen Wert zurückgeben, aber testFunction () erwartet, dass der Parameter eine Referenz ist, und gibt eine Warnung aus, weil dies nicht der Fall ist.
Sie können es außerhalb der Klasse testen wie:
%Vor%Es wird dieselbe Warnung ausgegeben! Das Problem liegt also nicht in der Klasse, das Problem ist diese Funktion.
Diese Funktion übergibt Funktionsparameter offensichtlich als statische Daten, ohne auf Variablen zu verweisen, und Funktionen, die sie aufruft, können nicht mit referenzierten Argumenten umgehen.
Tags und Links php pass-by-reference magic-methods dynamic-function