読者です 読者をやめる 読者になる 読者になる

肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

PHP 5.3 では組み込みオブジェクトのシリアライズができるようになりました

PHP

# これってドキュメントのどこかに書いてあるのでしょうか。。。?

名前空間、クロージャ、色々新しい機能がありすぎて注目度低めですが、わりかし大事なことかもしれません。w


#39821 のレポートでは、「それはバグではありません、仕様です」とはねかえされた、「組み込みオブジェクトはシリアライズができない」問題です。
たしかに、serializeのドキュメントのコメントにもそう書いてあります。

で、まあ、そういうことだったんですが、 #39821 の最後のコメントや、#41334 を見ればわかるとおり、PHP 5.3 で組み込みオブジェクトもシリアライズ→アンシリアライズでもとに戻せるようになりました。

検証用スクリプト

<?php
// ObjectSerialize

class Hoge
{
    public $a; 
    function __construct($a) { $this->a = $a; }
    function fuga() { return $this->a; }
}

// built-in object
echo "Built-in Object Serialize\n";
$d = new DateTime("2009-09-22");
echo "  Original: ". $d->format("Y-m-d") ."\n";
$s = serialize($d);
$d2 = unserialize($s);
echo "  Unserialized: " .$d2->format("Y-m-d") ."\n\n";

// user object
echo "User Object Serialize\n";
$d = new Hoge("2009-09-22"); // DateTime 関係ないけど出力をあわせるためにw
echo "  Original: ". $d->fuga() ."\n";
$s = serialize($d);
$d2 = unserialize($s);
echo "  Unserialized: " . $d2->fuga() ."\n\n";

実行結果

PHP 5.2.9

まず、PHP 5.2.9の実行結果を以下に。ユーザ定義のクラスのオブジェクトは元に戻せるけど、組み込みのDateTimeオブジェクトは元に戻せない。

Built-in Object Serialize
  Original: 2009-09-22
  Serialized: O:8:"DateTime":0:{}

Warning: DateTime::format(): The DateTime object has not been correctly initialized by its constructor in /home/sotarok/working/php/ObjectSerialize.php on line 18
  Unserialized: 

User Object Serialize
  Original: 2009-09-22
  Serialized: O:4:"Hoge":1:{s:1:"a";s:10:"2009-09-22";}
  Unserialized: 2009-09-22
PHP 5.3

で、PHP 5.3の実行結果。組み込みのものも、ユーザ定義のものも元に戻せる。

Built-in Object Serialize
  Original: 2009-09-22
  Serialized: O:8:"DateTime":3:{s:4:"date";s:19:"2009-09-22 00:00:00";s:13:"timezone_type";i:3;s:8:"timezone";s:16:"System/Localtime";}
  Unserialized: 2009-09-22

User Object Serialize
  Original: 2009-09-22
  Serialized: O:4:"Hoge":1:{s:1:"a";s:10:"2009-09-22";}
  Unserialized: 2009-09-22

なにが嬉しいか

自動でserializeしてデータを保存してる何かに、組み込みオブジェクトもそのまま突っ込めるね、ということですね。
例えば、PHPでmemcacheを使うと、 Memcache::set で保存したデータは、整数・文字列以外は自動でシリアライズされますが、これまでは、getしても戻せないという問題がありました。SimpleXMLElementとかもまんま保存できるよ!!(それがいいかどうかは別として)


などなど、まあserialize関数は、使いどころに注意する必要があることは間違いないですが、少し便利になりましたね。