スキップしてメイン コンテンツに移動

PHP8シリアライズで状態保存

PHP8シリアライズで状態保存

PHP8でのシリアライズの進化

PHP8ではシリアライズ機能が大幅に改善され、バイナリ化されたデータをより安全に扱えるようになりました。serialize()unserialize() は依然として主要な API ですが、オブジェクトの状態保存に関しては __sleep()__wakeup() を組み合わせることで、不要なプロパティを除外したり、再初期化処理を実行したりできます。

PHP8 の serialize() は、内部的にバイナリ化を行い、文字列として返却します。これにより、データ永続化の際にファイルやデータベースへそのまま保存でき、後で unserialize() で復元可能です。

serializeとunserializeの使い方

シリアライズはオブジェクトや配列を文字列に変換し、データ永続化やキャッシュに利用します。以下は典型的な使用例です。

$user = new User('alice', 30);
$serialized = serialize($user);
// ファイルへ保存
file_put_contents('user.dat', $serialized);

// 復元
$raw = file_get_contents('user.dat');
$restored = unserialize($raw);
echo $restored->getName(); // alice

注意点として、unserialize() は外部から渡されたデータをそのまま復元するため、信頼できない入力に対しては allowed_classes オプションを使ってクラスの許可リストを設定することが推奨されます。

__sleepと__wakeupでオブジェクト保存を最適化

オブジェクトをシリアライズする際に __sleep() を実装すると、シリアライズ前に必要なプロパティだけを返すことができます。逆に __wakeup() は復元後に呼び出され、リソースの再確立や初期化処理を行います。

class Connection {
    private $resource;
    private $host;

    public function __construct($host) {
        $this->host = $host;
        $this->resource = $this->connect();
    }

    private function connect() {
        // 実際の接続処理
    }

    public function __sleep() {
        // 接続リソースはシリアライズしない
        return ['host'];
    }

    public function __wakeup() {
        // 復元後に再接続
        $this->resource = $this->connect();
    }
}

このようにすることで、バイナリ化されたデータサイズを削減し、状態保存時の安全性を高められます。

ディープコピーとデータ永続化のベストプラクティス

オブジェクトのディープコピーは、serialize()unserialize() を組み合わせることで簡単に実現できます。これは「バイナリ化」を経由して完全なコピーを作る手法です。

$original = new User('bob', 25);
$copy = unserialize(serialize($original));
// $copy は $original と同一の状態を持つが、別オブジェクト

データ永続化においては、以下のポイントを押さえておくと安全かつ効率的です。

  • シリアライズ前に __sleep() で不要プロパティを除外する。
  • 復元時に __wakeup() でリソースを再確立する。
  • 外部入力からの unserialize()allowed_classes を設定し、クラスの許可リストを限定する。
  • 大規模データはバイナリ化された文字列を圧縮(例:gzcompress())して保存すると、ストレージコストを削減できる。

これらを組み合わせることで、PHP8 のシリアライズ機能を最大限に活用し、オブジェクト保存とディープコピーを安全に行うことができます。

この記事はAIによって作成されました。

コメント