はじめに
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
を使う場合と使わない場合の挙動を必ず理解しておく