Werden PHP-Variablen als Wert oder als Referenz übergeben?

Antworten:

311

Es ist nach Wert gemäß der PHP-Dokumentation .

Standardmäßig werden Funktionsargumente als Wert übergeben (sodass der Wert des Arguments innerhalb der Funktion nicht außerhalb der Funktion geändert wird, wenn er geändert wird). Damit eine Funktion ihre Argumente ändern kann, müssen sie als Referenz übergeben werden.

Stellen Sie dem Argumentnamen in der Funktionsdefinition ein kaufmännisches Und ( & ) voran, damit ein Argument für eine Funktion immer als Referenz übergeben wird .

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}

$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>
Michael Stum
quelle
4
Ich hatte auch diesen Zweifel (Neuling) - um ganz klar zu sein, wäre dies das gleiche, als $str = add_some_extra($str);würde ich die Referenz nicht verwenden, oder? Was ist dann der wahre Mehrwert davon?
Obmerk Kronen
7
@Obmerk Wenn Sie wurden nicht kaufmännische Verwendung anhand zu bedeuten, wäre es nicht gleichwertig sein. Beachten Sie, dass die Funktion keine return-Anweisung hat und daher $strin Ihrem Fall null zugewiesen wird.
Der unbekannte Entwickler
Wenn Sie dies auf diese Weise @ObmerkKronen tun, müssen Sie den Wert zurückgeben und ihn auch über Ihren Code abfangen. Die anfängliche Variable bleibt ansonsten gleich.
Nabeel Khan
Ich frage mich, ob die Referenzübergabe einige Leistungsvorteile hat oder nicht. Ich übergebe ein großes Array und standardmäßig wird es als Wert übergeben. Wenn ich dann Call by Reference verwende, gibt es dann einen leistungsbezogenen Vorteil? (Halten Sie die Array-Werte während des gesamten Prozesses unverändert)
Choxx
4
Der eigentliche Vorteil besteht darin, dass Sie mehrere Werte bearbeiten / zurückgeben können. Sie können auch Variablen als Referenz übergeben und die Funktion dennoch etwas zurückgeben lassen.
Martin Schneider
65

In PHP werden Objekte standardmäßig als Referenzkopie an ein neues Objekt übergeben.

Siehe dieses Beispiel .............

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
   $obj->abc = 30;
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30

Jetzt sehen Sie das ..............

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.

Jetzt sehen Sie das ..............

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue(&$obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.

Ich hoffe du kannst das verstehen.

Hardik
quelle
1
Dies zeigt sehr gut, wie PHP-Objekthandles funktionieren.
Frederik Krautwald
2
1. Beispiel: Der Wert der Referenz des Objekts wird an die Funktion übergeben. Änderungen am Objekt unter Verwendung der neuen Referenz werden auf alle anderen Referenzen angewendet, die auf dasselbe Objekt verweisen. 2. ex, wieder wird der WERT der Referenz des Objekts an die Funktion übergeben, die Funktion ändert den Wert der Referenz, um auf ein neues Objekt zu zeigen, das alte Objekt bleibt gleich. 3. Beispiel: Die Referenz des Wertes der Referenz des Objekts wird an die Funktion übergeben, so dass die Änderungen in der Funktion auf dasselbe Objekt wirken.
S-Jäger
Perfekte Beispiele und genau das, was ich mir vorgestellt hatte. Ich bin ein Neuling in PHP (aus Javascript / node.js Hintergrund) und manchmal ist es schwierig zu verstehen, was los ist, aber das ist sehr klar!
TKoL
Dieses Beispiel ist unnötig kompliziert. $ywird nicht benötigt - es gibt nichts function changeValue, was es erfordert, dass es sich im Inneren befindet class Y, so dass zwei nicht miteinander verbundene Konzepte miteinander verwickelt werden. Ich würde function changeValuezum äußeren Bereich übersteigen $x = new X();. Entfernen Sie alle Verweise auf $y. Jetzt ist es einfacher zu sehen, dass die ersten beiden Beispiele $ x in Ruhe lassen und das dritte seinen Inhalt in ändert new Y(). Was leichter zu sehen wäre, wenn Sie das typevon $x- die Tatsache, dass beide Xund Yzufällig ein $abcFeld enthalten, ist auch irrelevant für das, was demonstriert wird
ToolmakerSteve
60

Es scheint, dass viele Leute verwirrt sind, wie Objekte an Funktionen übergeben werden und was als Referenzmittel übergeben wird. Objektvariablen werden immer noch als Wert übergeben. Es ist nur der Wert, der in PHP5 übergeben wird, ein Referenzhandle. Als Beweis dafür:

<?php
class Holder {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return $this->value;
    }
}

function swap($x, $y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Ausgänge:

a, b

Um als Referenz zu übergeben , können wir die Variablen ändern, die vom Aufrufer gesehen werden. Was der obige Code eindeutig nicht tut. Wir müssen die Swap-Funktion ändern in:

<?php
function swap(&$x, &$y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Ausgänge:

b, a

um als Referenz zu übergeben.

grom
quelle
18
Ich denke, dieser Beweis ist eine Fehlinterpretation. Es sieht so aus, als hätten Sie versucht, Referenzen auszutauschen. Sie haben ein Problem mit der Zuweisung von Objekten. Sie weisen die unveränderliche Referenz neu zu. Es ist der Wert, auf den es zeigt, der von innen geändert werden kann. Die Neudefinition von Swap übergibt jetzt ** x, wodurch Sie * x ändern können. Das Problem besteht darin zu denken, dass $ x = $ y ändern würde, worauf $ x ursprünglich zeigt.
Grantwparks
9
Dies ist kein Beweis . Die Ausgabe des ersten Beispiels ist genau das, was Sie erwarten würden, wenn der aktuelle Wert des gesamten Objekts an die swapFunktion übergeben würde. mit anderen Worten, wenn Objekte "als Wert übergeben" wurden. Andererseits ist es auch genau das, was Sie erwarten würden, wenn ein Objekthandle an die Funktion übergeben würde, was tatsächlich passiert. Ihr Code unterscheidet nicht zwischen diesen beiden Fällen.
EML
31

http://www.php.net/manual/en/migration5.oop.php

In PHP 5 gibt es ein neues Objektmodell. Der Umgang von PHP mit Objekten wurde komplett neu geschrieben, um eine bessere Leistung und mehr Funktionen zu ermöglichen. In früheren Versionen von PHP wurden Objekte wie primitive Typen behandelt (z. B. Ganzzahlen und Zeichenfolgen). Der Nachteil dieser Methode war, dass semantisch das gesamte Objekt kopiert wurde, als eine Variable zugewiesen oder als Parameter an eine Methode übergeben wurde. Bei dem neuen Ansatz werden Objekte nach Handle und nicht nach Wert referenziert (man kann sich ein Handle als Objektkennung vorstellen).

Karl Seguin
quelle
25

PHP-Variablen werden nach Wert zugewiesen, nach Wert an Funktionen übergeben und beim Enthalten / Darstellen von Objekten als Referenz übergeben. Mit einem & können Sie das Übergeben von Variablen als Referenz erzwingen

Zugewiesen nach Wert / Referenzbeispiel:

$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";

print ("var1: $var1, var2: $var2, var3: $var3);

würde ausgeben

var1: Test, var2: Abschlusstest, var3: Abschlusstest

Übergeben von Wert / Referenz Exampe:

$var1 = "foo";
$var2 = "bar";

changeThem($var1, $var2);

print "var1: $var1, var2: $var2";

function changeThem($var1, &$var2){
    $var1 = "FOO";
    $var2 = "BAR";
}

würde ausgeben:

var1: foo, var2 BAR

Objektvariablen, die als Referenz übergeben werden exampe:

class Foo{
    public $var1;

    function __construct(){
        $this->var1 = "foo";
    }

    public function printFoo(){
        print $this->var1;
    }
}


$foo = new Foo();

changeFoo($foo);

$foo->printFoo();

function changeFoo($foo){
    $foo->var1 = "FOO";
}

Würde ausgeben:

FOO

(Das letzte Beispiel könnte wahrscheinlich besser sein ...)

cmcculloh
quelle
2
"Objekte" sind keine Werte in PHP5 und können nicht "übergeben" werden. Der Wert von $fooist ein Zeiger auf ein Objekt . $foowird als Wert an die Funktion übergeben changeFoo(), da changeFoo()ihr Parameter nicht mit a deklariert wurde &.
Newacct
9

Sie können eine Variable als Referenz an eine Funktion übergeben. Diese Funktion kann die ursprüngliche Variable ändern.

Sie können die Passage als Referenz in der Funktionsdefinition definieren:

<?php
function changeValue(&$var)
{
    $var++;
}

$result=5;
changeValue($result);

echo $result; // $result is 6 here
?>
Mahsin
quelle
6

Sie können es so oder so machen.

Wenn Sie ein '&' Symbol voranstellen, wird die Variable, die Sie übergeben, ein und dieselbe wie ihr Ursprung. dh: Sie können als Referenz übergeben, anstatt eine Kopie davon zu erstellen.

so

    $fred = 5;
    $larry = & $fred;
    $larry = 8;
    echo $fred;//this will output 8, as larry and fred are now the same reference.
Bingy
quelle
2
Dies ist veraltet und generiert eine Warnung
Fijiaaron
5

Variablen, die primitive Typen enthalten, werden in PHP5 als Wert übergeben. Variablen, die Objekte enthalten, werden als Referenz übergeben. Es gibt einen interessanten Artikel aus dem Linux Journal aus dem Jahr 2006, in dem dieser und andere OO-Unterschiede zwischen 4 und 5 erwähnt werden.

http://www.linuxjournal.com/article/9170

Polsonby
quelle
Alle Variablen werden in PHP als Wert übergeben, wenn der Parameter der Funktion keine hat &.
Newacct
1

Objekte werden in PHP 5 als Referenz und in PHP 4 als Wert übergeben. Variablen werden standardmäßig als Wert übergeben!

Lesen Sie hier: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html

Miha
quelle
"Objekte" sind in PHP5 keine Werte und können nicht "übergeben" werden. Alle Variablen werden als Wert übergeben, wenn der Parameter der übergebenen Funktion nicht vorhanden ist &.
Newacct
@ Newacct nicht ganz? Objekte werden etwas als Referenz übergeben . Ich denke, ich habe beobachtet, dass PHP-Objekte durch Funktionen geändert werden können, auch wenn sie nicht mit definiert sind& vor den Parametern in der Definition definiert wurden. Wenn sie als Wert übergeben würden, würde das Objekt in dem Bereich, der die Funktion mit ihr als Parameter aufgerufen hat, dies tun nicht betroffen sein.
Félix Gagnon-Grenier
3
@ FélixGagnon-Grenier: Auch hier sind "Objekte" keine Werte und können nicht "übergeben" werden. Sie können in PHP5 keine "Variable" haben, deren Wert ein "Objekt" ist. Sie können nur einen Wert haben, der eine Objektreferenz ist (dh einen Zeiger auf ein Objekt). Natürlich können Sie einem Objekt einen Zeiger nach Wert übergeben oder zuweisen und das Objekt, auf das es zeigt, ändern, indem Sie eine Methode aufrufen, die eine solche Änderung vornimmt. Das hat nichts mit Referenzübergabe zu tun. Welcher Typ ein Wert ist und ob ein Parameter Pass-by-Value / Pass-by-Reference ist, sind unabhängige und orthogonale Dinge.
Newacct
1
class Holder
{
    private $value;

    public function __construct( $value )
    {
        $this->value = $value;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function setValue( $value )
    {
        return $this->value = $value;
    }
}

class Swap
{       
    public function SwapObjects( Holder $x, Holder $y )
    {
        $tmp = $x;

        $x = $y;

        $y = $tmp;
    }

    public function SwapValues( Holder $x, Holder $y )
    {
        $tmp = $x->getValue();

        $x->setValue($y->getValue());

        $y->setValue($tmp);
    }
}


$a1 = new Holder('a');

$b1 = new Holder('b');



$a2 = new Holder('a');

$b2 = new Holder('b');


Swap::SwapValues($a1, $b1);

Swap::SwapObjects($a2, $b2);



echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";

echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";

Attribute können weiterhin geändert werden, wenn sie nicht als Referenz übergeben werden.

Ausgabe:

SwapObjects: b, a SwapValues: a, b

Ricardo Saracino
quelle
1

Für alle, die in Zukunft darauf stoßen, möchte ich dieses Juwel aus den PHP-Dokumenten teilen , die von einem anonymen Benutzer gepostet wurden :

Hier scheint es einige Verwirrung zu geben. Die Unterscheidung zwischen Zeigern und Referenzen ist nicht besonders hilfreich. Das Verhalten in einigen der bereits veröffentlichten "umfassenden" Beispiele kann in einfacheren, einheitlichen Begriffen erklärt werden. Hayleys Code zum Beispiel macht genau das, was Sie erwarten sollten. (Mit> = 5.3)

Erstes Prinzip: Ein Zeiger speichert eine Speicheradresse, um auf ein Objekt zuzugreifen. Jedes Mal, wenn ein Objekt zugewiesen wird, wird ein Zeiger generiert. (Ich habe mich noch nicht zu tief mit der Zend-Engine befasst, aber soweit ich sehen kann, gilt dies.)

2. Prinzip und Quelle der größten Verwirrung: Die Übergabe einer Variablen an eine Funktion erfolgt standardmäßig als Wertübergabe, dh Sie arbeiten mit einer Kopie. "Aber Objekte werden als Referenz übergeben!" Ein häufiges Missverständnis sowohl hier als auch in der Java-Welt. Ich habe nie eine Kopie von WAS gesagt. Die Standardübergabe erfolgt nach Wert. Immer. WAS jedoch kopiert und übergeben wird, ist der Zeiger. Wenn Sie "->" verwenden, greifen Sie natürlich auf dieselben Interna wie die ursprüngliche Variable in der Aufruferfunktion zu. Wenn Sie nur "=" verwenden, werden nur Kopien abgespielt.

3. Prinzip: "&" setzt automatisch und dauerhaft einen anderen Variablennamen / Zeiger auf dieselbe Speicheradresse wie etwas anderes, bis Sie sie entkoppeln. Es ist richtig, hier den Begriff "Alias" zu verwenden. Stellen Sie sich vor, Sie verbinden zwei Zeiger an der Hüfte, bis sie mit "unset ()" gewaltsam getrennt werden. Diese Funktionalität existiert sowohl im selben Bereich als auch wenn ein Argument an eine Funktion übergeben wird. Oft wird das übergebene Argument als "Referenz" bezeichnet, da in C und C ++ bestimmte Unterschiede zwischen "Übergeben nach Wert" und "Übergeben nach Referenz" deutlicher waren.

Denken Sie daran: Zeiger auf Objekte, nicht auf Objekte selbst, werden an Funktionen übergeben. Diese Zeiger sind KOPIEN des Originals, es sei denn, Sie verwenden "&" in Ihrer Parameterliste, um die Originale tatsächlich zu übergeben. Nur wenn Sie in die Interna eines Objekts graben, ändern sich die Originale.

Und hier ist das Beispiel, das sie liefern:

<?php

//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.

$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.

//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"

function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}

function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}

?>

Ich habe einen ausführlichen Blog-Beitrag zu diesem Thema für JavaScript geschrieben , aber ich glaube, dass er für PHP, C ++ und jede andere Sprache gleichermaßen gut geeignet ist, in der die Leute verwirrt zu sein scheinen, ob es sich um eine Wertübergabe oder eine Referenzübergabe handelt.

Es ist klar, dass PHP wie C ++ eine Sprache ist, die die Referenzübergabe unterstützt. Standardmäßig werden Objekte als Wert übergeben. Wenn Sie mit Variablen arbeiten, in denen Objekte gespeichert sind, ist es hilfreich, diese Variablen als Zeiger zu betrachten (da dies auf Assemblyebene im Grunde genommen der Fall ist). Wenn Sie einen Zeiger als Wert übergeben, können Sie den Zeiger trotzdem "verfolgen" und die Eigenschaften des Objekts ändern, auf das verwiesen wird. Was Sie nicht tun können, ist, es auf ein anderes Objekt zeigen zu lassen. Nur wenn Sie einen Parameter explizit als Referenz übergeben deklarieren, können Sie dies tun.

AleksandrH
quelle
0

Eigentlich sind beide Methoden gültig, aber es hängt von Ihren Anforderungen ab. Pass-Werte als Referenz machen Ihr Skript oft langsam. Es ist daher besser, Variablen nach Wert zu übergeben, indem der Ausführungszeitpunkt berücksichtigt wird. Außerdem ist der Codefluss konsistenter, wenn Sie Variablen nach Wert übergeben.

atif
quelle
0

Verwenden Sie diese Option für Funktionen, wenn Sie die ursprüngliche Variable einfach ändern und sie wieder auf denselben Variablennamen mit dem neuen zugewiesenen Wert zurücksetzen möchten.

function add(&$var){ // The &amp; is before the argument $var
   $var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
PPL
quelle
-7

Abhängig von der Version ist 4 nach Wert, 5 nach Referenz.

Karl Seguin
quelle
11
Ich denke nicht, dass das wahr ist.
Nick Heiner
@ Karl Seguin, es ist teilweise wahr. Bevor PHP5-Objekte standardmäßig als Wert übergeben wurden, werden sie seit 5 vom Handler übergeben, was in der Praxis (mit einigen Ausnahmen) als Referenz behandelt werden kann, da wir die Objekteigenschaften über sie ändern können. Php.net/manual/en/language. oop5.references.php .
Adam Faryna