43
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPでの参照渡し

Last updated at Posted at 2014-03-27

基本

デフォルト値無しの場合

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

コード
<?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
43
39
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?