はじめに
PHPのオブジェクトは、変数に代入すると同じインスタンスを参照する仕様になっています。
「代入するとコピーされる」と思ってしまうと、PHP8上級試験でつまずくポイントです。
この記事では、実際のコード例と図解(アスキーアート)を使って、オブジェクトの参照とcloneによる複製の違いをわかりやすく解説します。
目次
オブジェクト代入は参照渡し
PHPではオブジェクトを変数に代入すると、新しいインスタンスは作られず同じオブジェクトを参照します。
declare(strict_types=1);
error_reporting(-1);
class Hoge{
public function __construct(
public int $num,
){}
}
$obj = new Hoge(123);
$obj2 = $obj;
$obj2->num = 987;
var_dump($obj, $obj2);出力結果:
object(Hoge)#1 (1) { ["num"]=> int(987) }
object(Hoge)#1 (1) { ["num"]=> int(987) }#1が同じなのは、同じインスタンスを参照している証拠です$obj2->numを変更すると$objにも反映されます
図解で理解する参照の仕組み
代入直後の状態
$obj ──┐
│
▼
+-----------------+
| Hogeインスタンス#1 |
| num = 123 |
+-----------------+
$obj2 ──┘$obj と $obj2 は 同じインスタンス#1 を参照している
プロパティを書き換えた場合
$obj ──┐
│
▼
+-----------------+
| Hogeインスタンス#1 |
| num = 987 |
+-----------------+
$obj2 ──┘$obj2->num = 987 の変更が $obj にも反映される
clone で別インスタンスを作る場合
$obj2 = clone $obj;
$obj2->num = 987;$obj ──► +-----------------+
| Hogeインスタンス#1 |
| num = 123 |
+-----------------+
$obj2 ─► +-----------------+
| Hogeインスタンス#2 |
| num = 987 |
+-----------------+$objと$obj2は別インスタンス$obj2の変更は$objに影響しない
まとめ
- 「代入=コピー」と思わない
#1, #2のインスタンス番号を確認して参照関係を判断するcloneを使う場合と使わない場合の挙動を必ず理解しておく
