基本
デフォルト値無しの場合
関数定義で引数に &
をつけると、関数内で扱う変数名が呼び出し元のスコープに存在する変数名の エイリアス のようになる。
<?php
function increment(&$var) {
var_dump($var++);
}
$a = 1;
increment($a);
var_dump($a);
int(1)
int(2)
ここで、increment()
に変数ではなく 値 を渡すと Fatal Error になり、スクリプト実行が停止される。
<?php
function increment(&$var) {
var_dump($var++);
}
increment(1);
Fatal error: Only variables can be passed by reference in ... on line 5
代入式 を渡すと実行は可能ではあるが Strict Standards という旨のエラーが発生するので、可能な限りこう書くのは避けるべきである。
<?php
function increment(&$var) {
var_dump($var++);
}
increment($a = 1);
var_dump($a);
Strict Standards: Only variables should be passed by reference in ... on line 5
int(1)
int(2)
デフォルト値有りの場合
関数への参照渡しには値渡し同様にデフォルト値を設けることが可能である。何も渡さなかった場合は値渡しの場合の挙動と差異は無い。
<?php
function increment(&$var = 5) {
var_dump($var++);
}
increment();
5
PHPでは原則的に未定義の変数の値を取得しようとしたときに Notice が発生して NULL 扱いになるが、参照渡しのデフォルト値の場合だけ例外的にNoticeを発生せずにNULL
として初期化される。この場合、関数側でデフォルト値に何を指定してもNULL
と見なされることに注意する必要がある。
<?php
function increment(&$var = 5) {
var_dump($var++);
}
increment($a);
var_dump($a);
NULL
int(1)
型による違い
スカラー値・NULL
・配列
基本で述べたとおりで、特に言及点は無い。唯一気を付けることとすれば、 配列はオブジェクトでは無いことが挙がるだろうか。他の言語出身者からすれば少し違和感のある定義であると思われる。
リソース
リソースは自動的に連番で設定される リソースID によって管理されており、値渡しにしただけで感覚的には参照渡しのような扱いになる。しかし、関数内で変数に対して何か値を設定したところで、呼び出し元の変数に影響を与えるわけではない。あくまでリソースIDというスカラー値として考えると理解がしやすい。
<?php
function readline($fp) {
echo "2: "; var_dump($fp);
$line = rtrim(fgets($fp));
$fp = null;
echo "3: "; var_dump($fp);
return $line;
}
$fp = fopen('test.txt', 'r');
echo "1: "; var_dump($fp);
echo "4: "; var_dump(readline($fp));
echo "5: "; var_dump($fp);
1: resource(1) of type(stream)
2: resource(1) of type(stream)
3: NULL
4: String(1) "a"
5: resource(1) of type(stream)
参照渡しにした場合はリソースID自体に参照がかかるとして考えるといいだろう。
<?php
function readline(&$fp) {
echo "2: "; var_dump($fp);
$line = rtrim(fgets($fp));
$fp = null;
echo "3: "; var_dump($fp);
return $line;
}
$fp = fopen('test.txt', 'r');
echo "1: "; var_dump($fp);
echo "4: "; var_dump(readline($fp));
echo "5: "; var_dump($fp);
1: resource(1) of type(stream)
2: resource(1) of type(stream)
3: NULL
4: String(1) "a"
5: NULL
オブジェクト
オブジェクトもリソース同様にオブジェクトIDというスカラー値として考えると理解がしやすい。
<?php
function set_number_zero(stdClass $var) {
$var->number = 0;
echo "2: "; var_dump($var);
$var = null;
echo "3: "; var_dump($var);
}
$a = new stdClass;
echo "1: "; var_dump($a);
set_number_zero($a);
echo "4: "; var_dump($a);
1: object(stdClass)#1 (0) {
}
2: object(stdClass)#1 (1) {
["number"]=>
int(0)
}
3: NULL
4: object(stdClass)#1 (1) {
["number"]=>
int(0)
}
同様に、参照渡しにした場合はオブジェクトID自体に参照がかかるとして考えるといい。
<?php
function set_number_zero(stdClass &$var) {
$var->number = 0;
echo "2: "; var_dump($var);
$var = null;
echo "3: "; var_dump($var);
}
$a = new stdClass;
echo "1: "; var_dump($a);
set_number_zero($a);
echo "4: "; var_dump($a);
1: object(stdClass)#1 (0) {
}
2: object(stdClass)#1 (1) {
["number"]=>
int(0)
}
3: NULL
4: NULL
タイプヒンティングとNULL
タイプヒンティングを用いる場合、デフォルト値として設定するものはそのタイプに合致するものでなければならないが、例外的にNULL
だけは何に対しても設定が可能となる。
function dump_array(array $array = null) {
var_dump($array);
}
dump_array();
NULL