PHP変数は値または参照によって渡されますか?


回答:


311

PHPのドキュメントによれば、これは値によるものです。

デフォルトでは、関数の引数は値で渡されます(関数内の引数の値が変更されても、関数の外では変更されません)。関数が引数を変更できるようにするには、引数を参照で渡す必要があります。

関数への引数が常に参照によって渡されるようにするには、関数定義の引数名の前にアンパサンド()を付加します。

<?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.'
?>

4
私もこの疑問を持っていました(初心者)-明確にするために、これは$str = add_some_extra($str);参照を使用していない場合と同じですよね?次に、その真の付加価値は何ですか?
Obmerk Kronen 2013

7
@Obmerk 参照によって示すためにアンパサンドを使用していなかった場合、それは同等ではありません。この関数にはreturnステートメントがないため$str、nullが割り当てられていることに注意してください。
不明な開発

この方法で@ObmerkKronenを実行する場合は、値を返してコードでもキャッチする必要があります。それ以外の場合、初期変数は同じままです。
Nabeel Khan、2016

参照渡しにパフォーマンス上の利点があるかどうか疑問に思いますか?私は大きな配列を渡していますが、デフォルトでは値渡しです。したがって、参照による呼び出しを使用すると、パフォーマンスに関していくつかの利点がありますか??? (プロセス全体を通して配列値を変更せずに維持)
Choxx

4
実際の利点は、複数の値を操作/返すことができることです。変数を参照で渡し、関数が何かを返すようにすることもできます。
Martin Schneider

65

PHPでは、デフォルトでオブジェクトは参照コピーとして新しいオブジェクトに渡されます。

この例を参照してください.............

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

これを見てください..............

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.

これを見てください..............

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.

ご理解いただければ幸いです。


1
これは、PHPオブジェクトの処理方法をよく示しています。
Frederik Krautwald、2014年

2
1つ目は、objの参照の値が関数に渡され、新しい参照を使用してobjを変更すると、同じobjを指す他のすべての参照に反映されます。2番目の例では、objの参照のVALUEが関数に渡されます。関数は参照の値を変更して新しいobjを指すようにしますが、古いobjは同じままです。3番目の例では、objの参照の値の参照が関数に渡されるため、関数の変更は同じobjで動作しています。
s-hunter

完璧な例と正確に私が起こるだろうと思ったこと。私はPHPの初心者です(JavaScript / node.jsのバックグラウンドから)。何が起こっているのかを理解するのが難しい場合がありますが、これは非常に明確です!
TKoL

この例は不必要に複雑です。$yそれは必要ありません-それが中にあるfunction changeValueことを必要とするものは何もないclass Yので、2つの無関係な概念を絡み合わせます。function changeValueすぐ上の外側のスコープに移動し$x = new X();ます。への参照をすべて削除します$y。これで、最初の2つの例では$ xがそのままになり、3番目の例では内容がに変更されていることが簡単にわかりnew Y()ます。あなたがダンプかどうかを確認するために容易になるだろうどちらtype$x-の両方の事実XとはY含めることが起こる$abcフィールドをも実証されているものとは無関係である
ToolmakerSteve

60

多くの人は、オブジェクトが関数に渡される方法と参照渡しが何を意味するかについて混乱するようです。オブジェクト変数は引き続き値で渡されますが、PHP5で渡される値は参照ハンドルです。証拠として:

<?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";

出力:

a, b

するには、参照によって渡す手段我々は、発信者によって見られる変数を変更することができます。上記のコードは明らかにそうではありません。スワップ関数を次のように変更する必要があります。

<?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";

出力:

b, a

参照渡しするため。


18
この証明は誤解だと思います。参照を交換しようとしていたようです。オブジェクトの割り当て方法に問題があります。不変の参照を再割り当てしています。内部から変更できるのは、それが指す値です。swapの再定義で** xが渡されるようになりました。これにより、* xを変更できます。問題は、$ x = $ yが$ xが最初に指すものを変更すると考えることです。
grantwparks 2012年

9
これは証明ではありません。最初の例の出力は、オブジェクト全体の電流値が渡された場合、あなたが期待する正確に何であるswap機能。つまり、オブジェクトが「値渡し」された場合。一方、オブジェクトハンドルが関数に渡された場合に期待されることも、実際に行われることです。コードはこれら2つのケースを区別しません。
EML、2015年

31

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

PHP 5には、新しいオブジェクトモデルがあります。PHPのオブジェクトの処理は完全に書き直され、パフォーマンスと機能が向上しています。以前のバージョンのPHPでは、オブジェクトはプリミティブ型(整数や文字列など)のように処理されていました。このメソッドの欠点は、意味的には、変数が割り当てられたとき、またはメソッドにパラメーターとして渡されたときにオブジェクト全体がコピーされることでした。新しいアプローチでは、オブジェクトは値ではなくハンドルによって参照されます(ハンドルはオブジェクトの識別子と考えることができます)。


25

PHP変数は値によって割り当てられ、値によって関数に渡されます。また、オブジェクトを含む/表すときは、参照によって渡されます。&を使用して、変数を参照渡しにすることができます。

値/参照例によって割り当て:

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

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

出力します

var1:テスト、var2:最終テスト、var3:最終テスト

値渡し/参照例:

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

changeThem($var1, $var2);

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

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

出力:

var1:foo、var2 BAR

参照例によって渡されるオブジェクト変数:

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";
}

出力されます:

FOO

(その最後の例はおそらくもっと良いかもしれません...)


2
「オブジェクト」はPHP5では値ではないため、「渡す」ことはできません。値は、$fooあるオブジェクトへのポインタ$fooでパラメータを宣言しなかったため、関数に渡されますchangeFoo()changeFoo()&
newacct 2013年

9

変数を参照で関数に渡すことができます。この関数は、元の変数を変更できます。

関数定義で参照によってパッセージを定義できます。

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

$result=5;
changeValue($result);

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

6

あなたはどちらの方法でもそれを行うことができます。

'&'記号を前に置くと、渡す変数がその原点と同じになります。つまり、コピーを作成するのではなく、参照で渡すことができます。

そう

    $fred = 5;
    $larry = & $fred;
    $larry = 8;
    echo $fred;//this will output 8, as larry and fred are now the same reference.

2
これは非推奨であり、警告を生成します
fijiaaron

5

PHP5では、プリミティブ型を含む変数は値で渡されます。オブジェクトを含む変数は参照によって渡されます。2006年のLinux Journalには、これと他のオブジェクト指向の4と5の違いについて言及している興味深い記事があります。

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


関数のパラメータにがない場合、すべての変数はPHPで値によって渡されます&
newacct 2013年

1

オブジェクトは、PHP 5では参照渡し、PHP 4では値渡しされます。変数はデフォルトで値渡しされます。

ここをお読みください:http : //www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html


「オブジェクト」はPHP5では値ではないため、「渡す」ことはできません。渡される関数のパラメーターにがない場合、すべての変数は値で渡されます&
newacct 2013年

@newacctはお気に召しませんか?オブジェクトは参照によってやや渡されます。私は、phpオブジェクトが定義&のパラメーターの前で定義されていない場合でも関数によって変更できることを観察したと思います-それらが値によって渡された場合、パラメーターとして関数を呼び出したスコープに含まれるオブジェクトは影響を受けません。
フェリックスギャニオン-Grenierの

3
@FélixGagnon-Grenier:繰り返しになりますが、「オブジェクト」は値ではなく、「渡す」ことはできません。値が「オブジェクト」であるPHP5で「変数」を持つことはできません。オブジェクト参照(つまり、オブジェクトへのポインタ)である値のみを持つことができます。もちろん、値によってオブジェクトへのポインタを渡したり割り当てたりすることができ、そのような変更を行うメソッドを呼び出すことによって、ポインタが指すオブジェクトを変更することができます。これは参照渡しとは関係ありません。値のタイプと、パラメーターが値渡し/参照渡しかどうかは、独立した直交するものです。
newacct 2014

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>";

参照によって渡されない場合でも属性は変更可能であるため、注意してください。

出力:

SwapObjects:b、a SwapValues:a、b


1

将来これに遭遇した人のために、匿名ユーザーが投稿したPHPドキュメントからこの宝石を共有したいと思います

ここには混乱があるようです。ポインタと参照の違いは特に役に立ちません。すでに投稿されている「包括的な」例のいくつかの動作は、より単純な統一用語で説明できます。たとえば、Hayleyのコードは、期待どおりに正確に動作しています。(> = 5.3を使用)

最初の原則:ポインターは、オブジェクトにアクセスするためのメモリアドレスを格納します。オブジェクトが割り当てられるたびに、ポインタが生成されます。(私はまだZendエンジンについて深く掘り下げていませんが、私の知る限り、これは当てはまります)

第2の原則、そして最も混乱の元:関数への変数の受け渡しは、デフォルトでは値の受け渡しとして行われます。つまり、コピーで作業しています。「しかし、オブジェクトは参照によって渡されます!」こことJavaの世界の両方でよくある誤解。私は何のコピーを言ったことはありません。デフォルトの受け渡しは値によって行われます。常に。ただし、コピーされて渡されるのはポインタです。"->"を使用する場合は、もちろん、呼び出し元関数の元の変数と同じ内部にアクセスします。"="を使用するだけで、コピーのみが再生されます。

3番目の原則:「&」は、別の変数名/ポインターを、分離するまで、他のものと同じメモリアドレスに自動的かつ永続的に設定します。ここでは「エイリアス」という用語を使用するのが正しいです。"unset()"で強制的に分離されるまで、ヒップで2つのポインタを結合すると考えてください。この機能は、同じスコープ内と、引数が関数に渡される場合の両方に存在します。多くの場合、渡された引数は「参照」と呼ばれます。これは、「値による受け渡し」と「参照による受け渡し」の違いがCおよびC ++で明確になったためです。

ただ覚えておいてください。オブジェクト自体ではなく、オブジェクトへのポインタが関数に渡されます。パラメータリストで "&"を使用して実際にオリジナルを渡す場合を除き、これらのポインタはオリジナルのコピーです。オブジェクトの内部を掘り下げるときのみ、オリジナルが変更されます。

そして、ここにそれらが提供する例があります:

<?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.
}

?>

私はJavaScriptについてこのテーマについて詳細なブログ記事を書きましたが、 PHP、C ++、および参照渡しと値渡しについて混乱していると思われる他の言語にも同様に当てはまると思います。

明らかに、C ++と同様に、PHPは参照渡しをサポートする言語です。デフォルトでは、オブジェクトは値で渡されます。オブジェクトを格納する変数を操作する場合、それらの変数をポインターとして見ると役立ちます(アセンブリレベルでは、それが基本的には変数だからです)。ポインタを値で渡す場合でも、ポインタを「トレース」して、ポイントされているオブジェクトのプロパティを変更できます。できないことは、別のオブジェクトを指すようにすることです。パラメータを参照渡しとして明示的に宣言した場合にのみ、それを行うことができます。


0

実際にはどちらの方法も有効ですが、要件によって異なります。参照渡しの値を使用すると、スクリプトが遅くなることがよくあります。したがって、実行時間を考慮して、値で変数を渡すことをお勧めします。また、変数を値で渡すと、コードフローの一貫性が向上します。


0

元の変数を単に変更して、新しい値が割り当てられた同じ変数名に再び戻したい場合は、これを関数に使用します。

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

-7

バージョンによって異なりますが、4は値によるもので、5は参照によるものです。


11
これは本当だとは思いません。
ニックハイナー、

@カール・セギーン、それは部分的に本当です。PHP5以前はデフォルトでオブジェクトは値で渡されていましたが、5以降はハンドラーで渡されます。php.net/ manual / en / languageを介してオブジェクトプロパティを変更できるため、実際には参照として扱うことができます(一部の例外はあります)。 oop5.references.php
Adam Faryna
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.