CMS構築を目的にPHPをベースとしたWordPress、CakePHPやPEARなどオープンソースを中心に解説しています

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つ目」が正解でした。

ハマりやすそうな問題、かつ、無駄に時間を浪費しそうな問題です。
知識として片隅に置いておきたいです。

このエントリーをはてなブックマークに追加

Monthly Archives

Search