はじめに
PHP8上級試験では、オブジェクトのシリアライズ・アンシリアライズに関する問題が頻出です。
特に「コンストラクタは呼ばれる?デストラクタは呼ばれる?」という挙動は、誤解されやすいポイントです。
この記事では、コード例と視覚的なフロー図を使って、アンシリアライズ後のオブジェクトの挙動を整理します。
目次
コード例
<?php
declare(strict_types=1);
error_reporting(-1);
class Hoge{
public function __construct(){
$oid = spl_object_id($this);
echo __METHOD__ , "({$oid})\n";
}
public function __destruct(){
$oid = spl_object_id($this);
echo __METHOD__ , "({$oid})\n";
}
}
echo "start \n";
echo "new Hoge \n";
$obj = new Hoge();
echo "new object id is " , spl_object_id($obj) , "\n";
echo "serialize \n";
$s_str = serialize($obj);
echo "unserialize \n";
$obj2 = unserialize($s_str);
echo "unserialize object id is " , spl_object_id($obj2) , "\n";
echo "obj unset \n";
unset($obj);
echo "obj2 unset \n";
unset($obj2);
echo "end \n";
実行結果
start
new Hoge
Hoge::__construct(1)
new object id is 1
serialize
unserialize
unserialize object id is 2
obj unset
Hoge::__destruct(1)
obj2 unset
Hoge::__destruct(2)
end
オブジェクトライフサイクルを視覚化(フロー図)
[ new Hoge() ]
│
▼
__construct() 呼ばれる
│ (ID=1)
▼
$obj ────────────┐
│
serialize()
│
▼
$s_str (文字列化)
│
▼
unserialize($s_str)
│
▼
$obj2 (ID=2)
コンストラクタは呼ばれない
│
▼
使用中
│
┌────────────┴────────────┐
▼ ▼
unset($obj) unset($obj2)
__destruct() 呼ばれる __destruct() 呼ばれる
(ID=1) (ID=2)
覚えておきたいポイント
__construct()
はアンシリアライズ時には呼ばれない__destruct()
はオブジェクト破棄時に必ず呼ばれるspl_object_id()
は新しいインスタンスごとに一意のIDを持つ- 教材や問題集で「デストラクタも呼ばれない」と書かれている場合は注意
試験向けまとめ表
処理 | __construct() | __destruct() |
---|---|---|
new Hoge() | ✅ 呼ばれる | ✅ 破棄時に呼ばれる |
serialize() | ❌ 呼ばれない | ❌ 呼ばれない |
unserialize() | ❌ 呼ばれない | ❌ 呼ばれない(瞬間は) |
unset() / スクリプト終了時 | — | ✅ 呼ばれる |