PHP 変数は値または参照によって渡されますか?
17 に答える
PHP Documentationによると、値によるものです。
デフォルトでは、関数の引数は値で渡されます (そのため、関数内で引数の値が変更されても、関数の外では変更されません)。関数が引数を変更できるようにするには、それらを参照渡しする必要があります。
関数への引数が常に参照によって渡されるようにするには、関数定義で引数名の前にアンパサンド ( & ) を追加します。
<?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.'
?>
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.
これを理解していただければ幸いです。
オブジェクトが関数に渡される方法と、参照渡しの意味に混乱している人が多いようです。オブジェクトは引き続き値渡しされます。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
参照渡しとは、呼び出し元に表示される変数を変更できることを意味しますが、上記のコードでは明らかに変更できません。swap 関数を次のように変更する必要があります。
<?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
参照渡しするためです。
http://www.php.net/manual/en/migration5.oop.php
PHP 5 には、新しいオブジェクト モデルがあります。PHP のオブジェクト処理が完全に書き直され、パフォーマンスの向上と機能の追加が可能になりました。以前のバージョンの PHP では、オブジェクトはプリミティブ型 (整数や文字列など) のように扱われていました。このメソッドの欠点は、変数が割り当てられたとき、またはパラメーターとしてメソッドに渡されたときに、意味的にオブジェクト全体がコピーされることでした。新しいアプローチでは、オブジェクトは値ではなくハンドルによって参照されます (ハンドルはオブジェクトの識別子と考えることができます)。
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 バー
参照によって渡されるオブジェクト変数の例:
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";
}
出力:
フー
(最後の例はおそらくもっと良いかもしれません。)
参照によって関数に変数を渡すことができます。この関数は、元の変数を変更できます。
関数定義で参照によってパッセージを定義できます。
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
どちらの方法でも実行できます。
'&'記号を前に置くと、渡す変数が元の変数と同じになります。つまり、コピーを作成するのではなく、参照によって渡すことができます。
それで
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
PHP5 では、プリミティブ型を含む変数は値渡しされます。オブジェクトを含む変数は、参照によって渡されます。2006 年の Linux Journal からの非常に興味深い記事があり、これと 4 と 5 の間のその他の OO の違いについて言及しています。
オブジェクトは、PHP 5では参照によって、PHP 4では値によって渡されます。変数はデフォルトで値によって渡されます!
ここを読んでください:http ://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
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
実際には両方の方法が有効ですが、要件によって異なります。参照によって値を渡すと、多くの場合、スクリプトが遅くなります。したがって、実行時間を考慮して変数を値で渡す方がよいでしょう。また、変数を値で渡すと、コード フローの一貫性が向上します。
バージョンによって異なりますが、4 は値によるもの、5 は参照によるものです。