Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

Serializableインターフェース

via. PHP Serialization, Stack Traces, and Exceptions | Articles - Fabien Potencier

Serializableインターフェースがあったのか。。。見たことあるようなないような。。。

参照元の概要は、

  • symfonyのセッションストレージにデータベース+PDOを使っている場合、Formオブジェクトをserializeすると「You cannot serialize or unserialize PDO instances」が発生する
  • 調べていくと、Exceptionクラスを継承したsfValidatorErrorクラスで発生している
  • Exceptionオブジェクトをserializeしようとしても同様のエラーになった
<?php
$dbh = new PDO('sqlite:memory:');
 
function will_crash($dbh)
{
  // serialize an exception
  echo serialize(new Exception());
}
 
// this will throw a PDOException
will_crash($dbh);
  • 原因は、serializeする際、スタックトレースの内容もシリアライズしようとするため
  • しゃーないので、sfValidatorErrorクラスをSerializeインターフェースも実装するようにした

な感じです。

で、Serializableインターフェース。今ではPHPマニュアルにもあるようですが、こんな感じのインターフェースらしいです。

<?php
interface abstract Serializable
{
    public function serialize();
    public function unserialize($serialized);
}

このインターフェースで用意された

  • serializeメソッド
  • unserializeメソッド

を実装すると、serializeを呼び出したときの挙動を変えられるとのこと。参照元の解決策は、

<?php
class sfValidatorError extends Exception implements Serializable
{
  // class code
 
  public function serialize()
  {
    return serialize(array($this->validator, $this->arguments, $this->code, $this->message));
  }
 
  public function unserialize($serialized)
  {
    list($this->validator, $this->arguments, $this->code, $this->message) = unserialize($serialized);
  }
}

のように、sfValidatorErrorオブジェクトそのものではなく、必要な情報をシリアライズ・デシリアライズしてるようです。

なるほどねー。

ちなみに、JavaのSerializableインターフェースとは目的が違います(のハズ)。