PHP - クラス - オブジェクトの受け渡し

公開日:2020-12-22 更新日:2020-12-22
[PHP]

1. 概要

オブジェクトを引数や戻り値で受け渡す場合についてです。
数値、文字列、配列などを関数(メソッド)の引数や戻り値にする場合、
「&」を使わなければ、値のコピーによる受け渡しが行われますが、
値がオブジェクトだった場合は、「&」を使わなくても、参照による受け渡しが行われます。
そのため、渡されたオブジェクトの値を変更すると、元のオブジェクトも同じ値になります。

2. 引数と戻り値でオブジェクトを使用する例

次の例では、引数のオブジェクトの値をメソッド内で変更して、
戻り値で返したオブジェクトの値を変更しています。
ここで、元のオブジェクトを見ると、
class PersonalData {
    public $name;
    public $age;
}

$data1 = new PersonalData();
$data1->name    = 'ichiro';
$data1->age     = 1;

function test($data) {
    $data->age = 999;
    return $data;
}

$data2 = test($data1);
$data2->name = '一郎';

var_dump($data1);
実行結果
object(PersonalData)#1 (3) {
  ["name"]=>
  string(6) "一郎"
  ["age"]=>
  int(999)
}

3. 連想配列との違い

連想配列の場合、引数を参照で受け渡ししたい場合は、変数の前に「&」を付けます。
戻り値を参照にする場合は、呼び元と関数の前に、「&」を付けます。
呼び元にも「&」を付ける必要があるのが要注意です。

$data1 = [
    'name' => 'ichiro',
    'age'  => 1,
];

function &test(&$data) {
    $data['age'] = 999;
    return $data;
}

$data2 = &test($data1);
$data2['name'] = '一郎';

var_dump($data1);
array(2) {
  ["name"]=>
  string(6) "一郎"
  ["age"]=>
  int(999)
}

上記の3つある「&」を全てはずすと、
元の変数は、変更前のままとなります。
array(2) {
  ["name"]=>
  string(6) "ichiro"
  ["age"]=>
  int(1)
}

また、オブジェクトの場合は、=== で参照の比較、== で値の比較をしますが、
連想配列の場合は、別々に生成された連想配列でも、全ての要素の値が一致していれば、
=== で判定しても、同じ連想配列とみなします。
class PersonalData {
    public $name;
    public $age;
}

$data1 = new PersonalData();
$data1->name = 'ichiro';
$data1->age  = 1;

$data2 = new PersonalData();
$data2->name = 'ichiro';
$data2->age  = 1;
if ($data1 == $data2) {
    print("オブジェクトの値は同じです\n");
}
if ($data1 === $data2) {
    //ここは通らない
    print("全く同じオブジェクトです\n");
}

//連想配列
$data1 = ['name' => 'ichiro', 'age' => 1];
$data2 = ['name' => 'ichiro', 'age' => 1];
if ($data1 === $data2) {
    print("同じ連想配列です");
}
実行結果
オブジェクトの値は同じです
同じ連想配列です