Help us understand the problem. What is going on with this article?

PHPでの参照渡し

More than 5 years have passed since last update.

基本

デフォルト値無しの場合

関数定義で引数に & をつけると、関数内で扱う変数名が呼び出し元のスコープに存在する変数名の エイリアス のようになる。

コード
<?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
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした