クラスオブジェクトはシャローコピーなので、プログラムをクラスベース(オブジェクト指向)で作っていると、インスタンスの状況が分かりづらくなります。
それはPHPでも同じ。
インスタンスがどこを見てるかを確認できるのが変数の値を出力する var_dump() です。
PHPの関数には、変数の値をダンプするのに var_dump(), var_export(), print_r() があります。
ダンプは変数の中身をデータ型と値がフォーマットされて表示すること。
バグ調査などで使われ、運用環境のプログラムに書くものではありません。
その中で、var_dump()だけが、クラスオブジェクトのインスタンスの状況を確認できます。
クラスオブジェクトのことをインスタンスというんですが、インスタンスにはオブジェクトIDという番号が振られています。
var_dump()の表示内容には、そのオブジェクトIDが表示されます。
<?php
class Test
{
public $name = 'test';
}
$test1 = new Test();
$test2 = new Test();
$test3 = $test1;
var_dump($test1);
var_dump($test2);
var_dump($test3);
object(Test)#1 (1) {
["name"]=>
string(4) "test"
}
object(Test)#2 (1) {
["name"]=>
string(4) "test"
}
object(Test)#1 (1) {
["name"]=>
string(4) "test"
}
#(番号)のところがインスタンスのオブジェクトID。$test1 と $test2 は番号がちがうので、クラスは同じでもインスタンスはそれぞれ独立しています。
それに対し、$test3 と $test1 は、変数はちがえど見てるデータは同じ。
インスタンスのイコール(=)での代入はシャローコピーの真骨頂です。プログラミング初心者がかんちがいしやすいところ。
最初にも言ったように、var_exrpot() や print_r() では変数の内容は確認できますが、オブジェクトIDがないのでインスタンスの状況までは分かりません。
var_export($test1, false);
var_export($test2, false);
var_export($test3, false);
Test::__set_state(array(
'name' => 'test',
))Test::__set_state(array(
'name' => 'test',
))Test::__set_state(array(
'name' => 'test',
))
ちなみに、var_export() は改行がないので続けて表示されます。echo と同じですね?
print_r($test1);
print_r($test2);
print_r($test3);
Test Object
(
[name] => test
)
Test Object
(
[name] => test
)
Test Object
(
[name] => test
)
var_export(), print_r()でもクラスだということが分かるしその内容も分かります。このへんは使い分けですね。
ボクはつねに var_dump() を使ってるけど。
最後に、クラスのプロパティに同じクラスのインスタンスを代入して、同一クラスの数珠つなぎを作って表示してみましょう。
class Test
{
public $name = 'test';
public $obj;
}
$test1 = new Test();
$test2 = new Test();
$test2->obj = $test1;
$test3 = new Test();
$test3->obj = $test2;
$test1->name = 'change !!!';
var_dump($test1);
var_dump($test2);
var_dump($test3);
object(Test)#1 (2) {
["name"]=>
string(10) "change !!!"
["obj"]=>
NULL
}
object(Test)#2 (2) {
["name"]=>
string(4) "test"
["obj"]=>
object(Test)#1 (2) {
["name"]=>
string(10) "change !!!"
["obj"]=>
NULL
}
}
object(Test)#3 (2) {
["name"]=>
string(4) "test"
["obj"]=>
object(Test)#2 (2) {
["name"]=>
string(4) "test"
["obj"]=>
object(Test)#1 (2) {
["name"]=>
string(10) "change !!!"
["obj"]=>
NULL
}
}
}
クラスオブジェクトの数珠を作ったあとに $test1 を変更したのに、$test2, $test3 の中身も変わってます。
オブジェクトIDがあるのでそのメカニズムが良くわかりますね?
オブジェクト指向プログラミングに慣れてない人は注意しましょう。
(間違えやすくバグになりやすいので、もう1回言っとく。)