Menu
Coddy logo textTech

__serialize と __unserialize

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 49/91。

オブジェクトを保存または送信するために文字列へ変換する必要がある場合、PHPではシリアル化を使用します。__serialize()メソッドと__unserialize()マジックメソッドを使うと、どのdataを保存するか、またそれをどのように復元するかを正確に制御できます。

__serialize()メソッドはシリアライズするデータのarrayを返し、__unserialize()はそのarrayを受け取ってオブジェクトを再構築します。

<?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 "Created at: " . $restored->getCreatedAt();

createdAt がシリアライズから除外され、アンシリアライズ時に新しいタイムスタンプを取得することに注目してください。これは、機密データ、一時的な値、またはデータベース接続のようにシリアライズできないリソースを除外する場合に便利です。

これらのメソッドは PHP 7.4 で以前の __sleep() および __wakeup() メソッドに取って代わり、プロパティ名ではなくデータ配列を直接扱う、よりすっきりしたアプローチを提供します。

challenge icon

チャレンジ

簡単

__serialize()__unserialize() を使うと、どの data を保存するか、またどのように復元するかを制御できることを示す、ユーザープロファイルのキャッシュシステムを構築しましょう。

コードを2つのファイルに分けて整理します。

  • UserProfile.php:キャッシュ機能を持つユーザーのプロファイルを表す UserProfile class を Create します。constructor promotion を使用して、$userId(string)、$username(string)、$email(string)、$accessToken(string)の private properties を定義します。プロファイルが cached された時刻を保存する private $cachedAt property を add し、constructor で initially "not cached" に設定します。class には次の要素が必要です。
    • __serialize()userIdusernameemail のみを含む array を返します。accessToken には機密情報が含まれるため、決して serialize しないでください。cachedAt の timestamp は restore 時に再生成されます。
    • __unserialize():data array から userIdusernameemail を restore します。トークンは persist させるべきではないため、accessToken"expired" に設定します。
    • getInfo():次の format の string を返します:"[username] ([email]) - Token: [accessToken] - Cached: [cachedAt]"
  • main.php:UserProfile file を include します。4つの inputs、つまり user ID、username、email、access token を受け取ります。これらの値で UserProfile instance を Create します。次の3行を Print します。
    • original profile の info(before serialization)
    • serialize() を使用して profile を serialize し、次に unserialize() を使用して unserialize して restored profile を Create します。restored profile の info を Print します。
    • "Token preserved: yes" または "Token preserved: no" を Print します。これは、restored profile の token が original と matches するかどうかによって決まります(hint:restore 時に token は expired になるため、matches しないはずです)。

このパターンは、user data を安全に caching するために essential です。profile information は store したい一方で、access token のような機密性の高い credentials は決して persist したくありません。profile が cache から restore されると、token は expired とマークされ、application は新しい token を取得する必要があります。

自分で試してみよう

<?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: Print "Token preserved: yes" or "Token preserved: no"
// 復元されたプロファイルのトークンが元のものと一致するかどうかによって

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ