PHPの関数「unserialize」でエラーが発生する場合の対処方法です。
久しぶりにドツボにはまりました。。。
「serialize」で処理されたデータについて「unserialize」で元に戻そうとしたのですが、どうしてもエラーになってしまいます。
unserialize($data);
unserialize(): Error at offset xxx of xxx bytes
私のケースでは、FuelPHPでユーザ管理のモデルを作成し、プロフィールフィールドにデータを格納したときのお話です。
拡張性を持たせたテーブルのプロフィールフィールドは、1つのカラムに配列をシリアライズしたデータを格納します。
そのデータをSQLで取り出し、「unserialize」した時にエラーになってしまうのです。
ちなみに、現象が発生した環境は以下の通りです。
- Windows 7 64bit Professional
- Apache 2.4
- PHP 5.4
- FuelPHP 1.7
- MySQL 5.5
ネットで調べてみると、似たような現象がちらほら見受けられます。
基本的に、アンシリアライズする前のデータをデコードするという手法です。
1つ目に、関数「base64_decode」を使用した方法。
unserialize(base64_decode($data));
ダメです。。。改善されません。
2つ目に、関数「trim」を使用してトリムした方法。
unserialize(trim($data));
ダメです。
3つ目に、シリアライズされた文字列を置換する方法。いくつかパターンあるようです。
$data1= preg_replace('!s:(d+):"(.*?)";!e', "'s:'.strlen('$2').':"$2";'", $data); unserialize($data1); $data2 = preg_replace('/;n;/', ';N;', $data); unserialize($data2);
どちらもダメです。
4つ目に、一旦UTF8にエンコードしてみる方法。
unserialize(utf8_encode($data)); unserialize(utf8_decode($data));
エンコードでもデコードでも変わらず。
5つ目に、関数「stripslashes」を使用した方法。
unserialize(stripslashes($data));
ダメです。
6つ目に関数「html_entity_decode」を使用した方法。
unserialize(html_entity_decode($data));
通った!エラーが発生しなくなりました!
今回はFuelPHPのモデルで拡張カラム「profile_fields」にシリアライズしたデータを登録した場合の解決方法でした。
データを渡す際に「htmlentities」を実行したり、サーバの設定やPHP、FuelPHPの設定も見直してみましたが改善されませんでした。
やはり取り出す際に「html_entity_decode」は必要なようです。
「unserialize」でエラーが発生する事象は少なくないようで、多くのページがヒットしました。
上に挙げた解決方法はどれも間違いではなく、実際に解決したケースが紹介されています。
ただ、今回、私の場合は「6つ目」が正解でした。
ハマりやすそうな問題、かつ、無駄に時間を浪費しそうな問題です。
知識として片隅に置いておきたいです。