例えば64bit OS上で、あるデータを serialize します。
次に32bit OSでこの値を取得して unserialize した場合のお話。
レアなケースとは思いますが、それにハマってしまったので一応共有。
現象
64bit OSから、例えば次のようなコードで、配列をシリアライズして memcache に保存します。
$x = '1062430001292'; $a[$x] = $x; $v = serialize($a); $m->set('test', $v);
本来 memcache::set を使うなら serialize 不要ですが、ここは分り易くするために。
で、この値を32bit OS側から取得してやります。
$v = $m->get('test'); $a = unserialize($v); print_r($a);
すると、結果は次のようになってしまいます。
Array ( [1573079180] => 1062430001292 )
添え字と値は同じものを指定していたはずですが、全く異なる値になってしまいます。
原因
書き込む前の、64bit OS上での $a を var_dump してみます。
array(1) { [1062430001292]=> string(13) "1062430001292" }
そして、serialize した $v の値を見てみましょう。
a:1:{i:1062430001292;s:13:"1062430001292";}
一見良さそうですが、問題点が潜んでいます。
a:1:{i:1062430001292;s:13:"1062430001292";}
そう、添え字が int となってしまっています。
明示的にキャストしたり、色々と試してみましたが、添え字の中身が全て数値の場合はどうしても int と識別してしまう様子。
そのため、32bit OSの int では桁が足りず、32bit分だけの数値になってしまうワケですね。
対処方法
我々のプロジェクトでは、添え字の値は捨てることで対応可能でした。
しかしいつもそういった対応が可能とは限りません。
出来るならば、例えばアタマに “id” と付けるなど、イヤでも文字列になるような対処も方法のひとつだと思います。
$x = '1062430001292'; $a["id:{$x}"] = $x;
それも難しければ、serialize した後で文字列に無理矢理変換する方法もあるかもしれませんが、オススメはしにくいですよね。
a:1:{i:1062430001292;s:13:"1062430001292";}
↓
a:1:{s:13:"1062430001292";s:13:"1062430001292";}
Related posts: