PHP のリファレンスにより二つの変数が同じ内容を参照することが可能です。 つまり、以下のようなものを実行した場合です。
<?php
$a =& $b;
?>
この場合、$a と $b は同じ内容を 指します。
注意: ここで、$a と $b は完全に 同じで、$a が $b を 指しているわけではなく、その逆でもありません。$a と $b は同じ場所を指しているのです。
注意: リファレンスを含む配列をコピーする際に、そのリファレンスが解消される ことはありません。配列を関数に値渡しする場合も同様です。
注意: 未定義の変数のリファレンスに対して代入したり 渡したり返したりすると、そこで変数が作成されます。
例1 未定義の変数のリファレンスの使用
<?php
function foo(&$var) { }
foo($a); // $a が作成され、null が代入されます
$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)
$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
リファレンスを返す関数や new 演算子でも 同じ構文が使用可能です(PHP 4.0.4 以降)。
<?php
$bar =& new fooclass();
$foo =& find_var($bar);
?>
PHP 5 以降、new は自動的にリファレンスを返すようになりました。そのため、この場面で =& を使用することは非推奨となり、 E_STRICT レベルのメッセージが表示されるようになりました。
注意: & 演算子を使用しない場合は、オブジェクトのコピーが 作成されます。クラスの内部で $this を使用した場合、 それはクラスの現在のインスタンスに対する操作を表します。 & のない代入はインスタンス(オブジェクト)のコピーを 行い、$this はそのコピーに対する操作を表します。 これはお望みの動作と異なるかもしれません。パフォーマンスやメモリ使用量の 観点から、常に単一のインスタンスに対して操作を行いたくなることもあるでしょう。
コンストラクタ内で @new のようにして @ 演算子を使用すると、あらゆるエラーの表示を 見えなくすることが可能ですが、 &new を使用する場合にはこの機能は動作しません。 Zend Engine の仕様により、これはパースエラーとなります。
関数の内部で global 宣言された変数にリファレンスを 代入すると、そのリファレンスは関数の内部でのみ参照可能となります。 これを避けるには、$GLOBALS 配列を使用します。
例2 関数内でのグローバル変数の参照
<?php
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // 関数の内部でのみ参照可能
} else {
$GLOBALS["var2"] =& $var1; // 関数の外部でも参照可能
}
}
global_references(false);
echo "var2 の値は '$var2'\n"; // var2 の値は ''
global_references(true);
echo "var2 の値は '$var2'\n"; // var2 の値は 'Example variable'
?>
global $var; は、$var =& $GLOBALS['var']; の短縮版だと考えてください。 これにより、他のリファレンスを $var に代入し、 ローカル変数のリファレンスのみを変更します。
注意: foreach ステートメントの内部でリファレンス変数に値を代入すると、リファレンスも変更されます。
例3 リファレンスと foreach ステートメント
<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
// 何かを実行します
}
echo $ref; // 3 - 配列の最後の要素
?>
リファレンスの第 2 の使用法は、変数のリファレンス渡しです。この場合、 関数でローカル変数が作成され、コール側の変数が、それと同じ内容への リファレンスとなります。例を示します。
<?php
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
?>
この結果、$a は 6 となります。これは、関数 foo の中では、変数 $var は $a と同じ内容を指しているためです。 より詳細な説明は、 リファレンス渡し を参照ください。
リファレンスの第 3 の使用法は、 リファレンスによる返り値 です。