あるクラスのインスタンスをシリアライズしたいけど、そのインスタンスには速度を稼ぐためにキャッシュを持っていたり、DBとの接続オブジェクトのインスタンスも持っていたりするので、そういうのはシリアライズしたくない。
こういう、あるフィールドはシリアライズするけどあるフィールドはしない、みたいなことを実現するための仕組みがあるのか調べてみた。2つあるらしい。
__sleep()と__wakeup()を使う
__sleep()はserialize()の前に実行される関数。_sleep()はシリアライズしたいフィールド名を文字列の配列の形で返すメソッド。つまり、__sleep()が返してきた文字列が表すフィールドのみをシリアライズする。
__wakeup()は、unserialize()の後に実行される関数で、シリアライズされなかったフィールドの初期化を行う。
Serializableインターフェイスを実装する
Serializableインターフェースが、実装することを要求するメソッドは
- serialize
- unserialize
で、前者でシリアライズを、後者でアンシリアライズをする。シリアライズしたい時は、対象のインスタンスobjに対して、
$obj->serialize();
ってやるんじゃなくて、あくまで従来の関数のシンタックスで呼び出すみたいだ。確かに、そうしないとアンシリアライズの時にどう書いて良いかわからんよな。
マニュアルでは、シリアライズ対象のインスタンスがフィールドを一個しか持たないけど、複数持つ場合どうしたら良いか分からなかった。とりあえず配列に格納してシリアライズしてみた。