__serialize & __unserialize
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 49/91。
オブジェクトを保存や転送のために文字列に変換する必要がある場合、PHPはシリアル化(serialization)を使用します。__serialize() および __unserialize() マジックメソッドを使用すると、どのデータが保存され、どのように復元されるかを正確に制御できます。
__serialize() メソッドはシリアル化されるデータの配列を返し、一方 __unserialize() はその配列を受け取ってオブジェクトを再構築します。
<?php
class Session {
public function __construct(
private string $userId,
private array $data,
private int $createdAt
) {}
public function __serialize(): array {
return [
'userId' => $this->userId,
'data' => $this->data
];
}
public function __unserialize(array $data): void {
$this->userId = $data['userId'];
$this->data = $data['data'];
$this->createdAt = time();
}
public function getCreatedAt(): int {
return $this->createdAt;
}
}
$session = new Session("user123", ["theme" => "dark"], time());
$serialized = serialize($session);
$restored = unserialize($serialized);
echo "User: " . $restored->getCreatedAt();
createdAt がシリアル化から除外され、非シリアル化時に新しいタイムスタンプを取得することに注目してください。これは、機密データや一時的な値、あるいはデータベース接続のようにシリアル化できないリソースを除外するのに役立ちます。
これらのメソッドは、PHP 7.4 において古い __sleep() および __wakeup() メソッドを置き換えたもので、プロパティ名の代わりにデータ配列を直接操作する、よりクリーンなアプローチを提供します。
チャレンジ
簡単__serialize() と __unserialize() を使用して、どのデータを保存し、どのように復元するかを制御する方法を示すユーザープロファイルキャッシュシステムを構築しましょう。
コードは2つのファイルに分けて構成します:
UserProfile.php— キャッシュ機能を備えたユーザーのプロファイルを表すUserProfileクラスを作成します。コンストラクタのプロパティ昇格(constructor promotion)を使用して、$userId(string)、$username(string)、$email(string)、および$accessToken(string) のプライベートプロパティを定義します。プロファイルがいつキャッシュされたかを保存するプライベートな$cachedAtプロパティを追加します(コンストラクタで初期値を"not cached"に設定します)。クラスには以下が必要です:__serialize()—userId、username、およびemailのみを含む配列を返します。accessTokenは機密情報であるため、シリアル化しないでください。cachedAtタイムスタンプは復元時に再生成されます。__unserialize()— データ配列からuserId、username、およびemailを復元します。accessTokenを"expired"に設定します(トークンは永続化すべきではないため)。getInfo()—"[username] ([email]) - Token: [accessToken] - Cached: [cachedAt]"という形式の文字列を返します。
main.php— UserProfile ファイルをインクルードします。ユーザーID、ユーザー名、メールアドレス、アクセストークンの4つの入力を受け取ります。これらの値を使用してUserProfileインスタンスを作成します。次の3行を出力してください:- 元のプロファイルの情報(シリアル化前)
serialize()を使用してプロファイルをシリアル化し、次にunserialize()を使用して復元されたプロファイルを作成します。復元されたプロファイルの情報。- 復元されたプロファイルのトークンが元のトークンと一致するかどうかに応じて、
"Token preserved: yes"または"Token preserved: no"を出力します(ヒント:復元時にトークンは期限切れになるため、一致しないはずです)。
このパターンは、ユーザーデータを安全にキャッシュするために不可欠です。プロファイル情報は保存したいが、アクセストークンのような機密性の高い資格情報は決して永続化させたくない場合に有効です。プロファイルがキャッシュから復元されると、トークンは期限切れとしてマークされ、アプリケーションに新しいトークンの取得を促します。
チートシート
マジックメソッドの __serialize() と __unserialize() は、シリアル化中にどのデータが保存され、オブジェクトがどのように復元されるかを制御します。
__serialize() は、シリアル化されるデータの配列を返します:
<?php
public function __serialize(): array {
return [
'userId' => $this->userId,
'data' => $this->data
];
}__unserialize() は配列を受け取り、オブジェクトを再構築します:
<?php
public function __unserialize(array $data): void {
$this->userId = $data['userId'];
$this->data = $data['data'];
$this->createdAt = time();
}オブジェクトを文字列に変換するには serialize() を、復元するには unserialize() を使用します:
<?php
$serialized = serialize($session);
$restored = unserialize($serialized);これらのメソッドは、機密データ、一時的な値、またはシリアル化できないリソース(データベース接続など)を除外するのに役立ちます。プロパティは、アンシリアル化中に新しい値で再生成することができます。
自分で試してみよう
<?php
require_once 'UserProfile.php';
// 入力を読み込む
$userId = trim(fgets(STDIN));
$username = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$accessToken = trim(fgets(STDIN));
// TODO: 入力値を使用してUserProfileインスタンスを作成する
// TODO: 元のプロファイル情報を表示する(シリアル化前)
// TODO: プロファイルをシリアル化し、その後アンシリアル化して復元されたプロファイルを作成する
// TODO: 復元されたプロファイル情報を表示する
// TODO: 復元されたプロファイルのトークンが元のものと一致するかどうかに応じて、
// "Token preserved: yes" または "Token preserved: no" を表示する
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
8マジックメソッド
マジックメソッド入門__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone とオブジェクトのクローン__serialize & __unserializeまとめ - カスタムコレクション