simplexml_load_string で xml をパースできるのはとても便利。
しかし serialize との相性は悪い。
PHP 5.2.10 にて |
---|
Warning: unserialize(): Node no longer exists in /path/to/hoge.php on line 11
ググってみると、どうやら、simplexml_load_string() で生成したオブジェクト(SimpleXMLObject)をシリアライズすると、unserialize() で元に戻せない PHP のバグであることが判明。
少し考えた末、シリアライズは必須だが、データ形式はオブジェクトである必要はないので、オブジェクト(SimpleXMLObject)を配列にキャストした後、シリアライズすることにした。
以下は、オブジェクトを再帰的に配列にキャストする toArray 関数です。
/** * recursive toArray * @param $mixed */ function toArray($mixed) { if (is_array($mixed)) { return array_map('toArray', $mixed); } elseif (is_object($mixed)) { return array_map('toArray', (array)$mixed); } else { return $mixed; } }
class 内でメソッドとして定義する時は、array_map の第一引数を array('self', 'toArray') のようにします。
※. php4系の場合は、array('クラス名', 'toArray') とします。
php4では simplexml_load_string() がサポートされてませんでした。
/** * recursive toArray * @access protected * @static */ protected static function toArray($mixed) { if (is_array($mixed)) { return array_map(array('self', 'toArray'), $mixed); } elseif (is_object($mixed)) { return array_map(array('self', 'toArray'), (array)$mixed); } else { return $mixed; } }
上記の toArray を実装後、以下のようにシリアライズして解決しました。
旧)
$sx = simplexml_load_string($xml); $serial = serialize($sx);
新)
$sx = simplexml_load_string($xml); $serial = serialize(self::toArray($sx)); // toArray で配列にキャスト
$serial = serialize(toArray($sx));