Warum unterstützt die Funktion call_user_func () von PHP nicht die Übergabe als Referenz?

8

Warum unterstützt die Funktion, die Funktionen wie call_user_func() unterstützt, die Parameter nicht als Referenz?

Die Dokumente sagen knappe Dinge wie "Beachten Sie, dass die Parameter für call_user_func () nicht als Referenz übergeben werden." Ich nehme an, dass die PHP-Entwickler in diesem Fall einen Grund hatten, diese Funktion zu deaktivieren.

Hatten sie eine technische Einschränkung? War es eine Sprachdesign-Wahl? Wie ist das zustande gekommen?

BEARBEITEN:

Um dies zu verdeutlichen, hier ein Beispiel.

%Vor%

Dies funktioniert normal; call_user_func übergibt $ count by reference nicht, obwohl more () es als referenzierte Variable deklariert hat. Die Dokumentation von call_user_func sagt klar, dass dies so ist, wie es funktionieren soll.

Ich bin mir bewusst, dass ich mit call_user_func_array('more', array(&$count)) den gewünschten Effekt erzielen kann.

Die Frage ist: Warum wurde call_user_func entworfen , um so zu arbeiten? Die Weitergabe der Referenzdokumentation besagt, dass "Funktionsdefinitionen allein ausreichen, um das Argument korrekt als Referenz zu übergeben . " Das Verhalten von call_user_func ist eine Ausnahme. Warum?

    
Will Martin 07.06.2011, 01:10
quelle

4 Antworten

10

Die Antwort ist tief in die Art und Weise eingebettet, wie Referenzen in PHPs Modell funktionieren - nicht unbedingt die Implementierung , denn das kann besonders im 5.x sehr variieren Versionen. Ich bin sicher, dass Sie die Zeilen gehört haben, sie sind nicht wie C-Zeiger, oder C ++ - Verweise, etc etc ... Grundsätzlich, wenn eine Variable zugewiesen oder gebunden ist, kann es auf zwei Arten geschehen - entweder nach Wert Falls die neue Variable an eine neue "Box" gebunden ist, die eine Kopie des alten Wertes enthält, oder durch Referenz (in diesem Fall wird die neue Variable an das gleiche Wertfeld wie der alte Wert gebunden). Dies gilt unabhängig davon, ob es sich um Variablen oder Funktionsargumente oder um Zellen in Arrays handelt.

Die Dinge beginnen ein bisschen haarig zu werden, wenn Sie beginnen, Referenzen in Funktionen zu übergeben - offensichtlich ist es die Absicht, die ursprünglichen Variablen modifizieren zu können. Vor einiger Zeit wurde Call-Time-Pass-by-Reference (die Fähigkeit, einen Verweis in eine Funktion zu übergeben, die keinen erwartet hat) veraltet, weil eine Funktion, die nicht wusste, dass es sich um eine Referenz handelte, "versehentlich" 'Ändern Sie die Eingabe. Wenn sie auf eine andere Ebene gebracht wird, wenn diese Funktion eine zweite Funktion aufruft, die selbst keine Referenz erwartet hat, dann wird alles getrennt. Es könnte funktionieren, aber es ist nicht garantiert und kann in einer PHP-Version einbrechen.

Hier kommt call_user_func() ins Spiel. Angenommen, Sie geben einen Verweis ein (und erhalten die zugehörige Call-Time-Warnung "Pass-by-Reference"). Dann wird Ihre Referenz an eine neue Variable gebunden - die Parameter von call_user_func() selbst. Wenn dann Ihre Zielfunktion aufgerufen wird, sind ihre Parameter nicht an die erwarteten Stellen gebunden. Sie sind nicht an die ursprünglichen Parameter gebunden. Sie sind an die lokalen Variablen gebunden, die sich in der Deklaration call_user_func() befinden. call_user_func_array() erfordert auch Vorsicht. Das Einfügen einer Referenz in eine Array-Zelle könnte zu Problemen führen - da PHP dieses Array mit der Semantik "Copy-on-Write" übergibt, können Sie nicht sicher sein, ob das Array unter Ihnen nicht modifiziert wird und die Kopie nicht erhalten wird losgelöst von der ursprünglichen Referenz.

Die aufschlussreichste Erklärung, die ich gesehen habe (was mir geholfen hat, Referenzen zu verstehen), war ein Kommentar zum PHP-Handbuch "passing by reference":

Ссылка

Grundsätzlich läuft die Logik so. Wie würdest du deine eigene Version von call_user_func() schreiben? - und dann erklären, wie das mit Referenzen bricht, und wie es scheitert, wenn Sie Call-Time-Pass-by-Reference vermeiden. Mit anderen Worten, die richtige Möglichkeit, Funktionen aufzurufen (den Wert anzugeben und PHP aus der Funktionsdeklaration entscheiden zu lassen, ob ein Wert oder eine Referenz übergeben werden soll) funktioniert nicht, wenn Sie call_user_func() - verwenden. Sie rufen zwei tiefe Funktionen auf, die erste nach Wert und die zweite nach den Werten in der ersten.

Machen Sie sich damit vertraut, und Sie werden ein viel tieferes Verständnis von PHP-Referenzen haben (und eine viel größere Motivation, sich klar zu verhalten, wenn Sie können).

    
Chris Nash 20.06.2012, 18:39
quelle
3

Siehe Folgendes:

Ссылка

Ist es möglich Parameter per Referenz übergeben mit call_user_func_array ()?

Ссылка

Die Übergabe von Referenzen in einem Array funktioniert ordnungsgemäß.

    
Tomasz Kowalczyk 07.06.2011 01:17
quelle
3

Aktualisierte Antwort:

Sie können verwenden:

%Vor%

um den gleichen Effekt zu erzielen wie:

%Vor%

Aus diesem Grund glaube ich (unbegründet), dass call_user_func nur eine Compiler-Zeitverkürzung ist. (d. h. es wird zum Kompilierungszeitpunkt durch das spätere ersetzt) ​​

Um meine Meinung zu Ihrer aktuellen Frage zu erfahren: "Warum wurde call_user_func so konzipiert, dass sie so funktioniert?":

Es fällt wahrscheinlich unter die gleichen Zeilen wie "Warum ist einige Methoden strstr und andere str_replace ?, warum Array-Funktionen haystack, needle und String-Funktionen needle, haystack ?

Es liegt daran, dass PHP von vielen verschiedenen Leuten über einen langen Zeitraum hinweg entwickelt wurde, ohne dass strenge Standards vorhanden waren.

Ursprüngliche Antwort:

Sie müssen sicherstellen, dass Sie die Variable innerhalb des Arrays auch auf eine Referenz setzen.

Versuchen Sie dies und notieren Sie sich den array(&$t) -Teil:

%Vor%

Sollte ausgeben:

%Vor%     
Petah 07.06.2011 01:18
quelle
2

Eine andere Möglichkeit - die By-Reference-Syntax bleibt richtig:

%Vor%     
Tommy 23.02.2013 11:12
quelle