6

PHP では、オブジェクトの大規模な配列 (100000 以上のオブジェクト) でserialize/を使用するのに非常に苦労しています。unserializeこれらのオブジェクトは、さまざまな種類のオブジェクトにすることができますが、すべて基本クラスの子孫です。

どういうわけかunserialize、オブジェクトの配列で使用すると、オブジェクトの約 0,001% が間違って生成されます! 代わりに、まったく異なるオブジェクトが生成されます。これはランダムに発生するのではなく、毎回同じオブジェクトで発生します。しかし、配列の順序を変更すると、別のオブジェクトで発生するため、これはバグのように見えます。

json_encode/に切り替えましたが、これは常にオブジェクトのクラスとしてjson_decode使用されることがわかりました。stdClass各オブジェクトのクラス名をプロパティとして含めることでこれを解決し、このプロパティを使用して新しいオブジェクトを構築しましたが、このソリューションはあまりエレガントではありません。

var_exportwithを使用するとeval問題なく動作しますが、他の方法よりも約 3 倍遅くなり、より多くのメモリを使用します。

今私の質問は次のとおりです。

  • で作成されたバグ/間違ったオブジェクトの原因は何 unserializeですか?
  • json_decodeクラスが自動的にjson内に保存されるように、オブジェクトの配列で使用するより良い方法はありますか?
  • PHPでオブジェクトの大きな配列を読み書きするための他の方法さえありますか?

アップデート

msgpack_serialize(php 拡張子、 の代替serialize) を使用すると、同じ種類のエラーが発生するため (しかし、不思議なことに、同じオブジェクトが間違って生成されるわけではありません!) 、配列データに何か奇妙なことがあるに違いないと考え始めています。

更新 2

解決策が見つかりました:serialize配列全体で行うのではなく、各オブジェクトで最初serializeに実行してからbase64_encode、シリアル化された各オブジェクトをテキストファイルの個別の行として保存します。file()このようにして、オブジェクトの配列全体を生成し、 withunserializeおよびを使用して各オブジェクトを反復処理できますbase64_decode 。これ以上エラーは発生しません!

4

1 に答える 1

4

serialize/unserialize 関数を使用すると、2 つのマジック メソッドが接続されます。

__寝る()

serialize() は、クラスにマジック ネーム __sleep() を持つ関数があるかどうかをチェックします。その場合、その関数はシリアル化の前に実行されます。オブジェクトをクリーンアップでき、シリアル化する必要があるそのオブジェクトのすべての変数の名前を含む配列を返すことになっています。メソッドが何も返さない場合は、NULL がシリアル化され、E_NOTICE が発行されます。

スリープを使用すると、シリアル化アクションをより適切に制御できます。シリアル化できる変数を渡すことができ、シリアル化の前にリソースをクリーンアップできます。

unserialize が呼び出されると、他の関数が言及される必要があります

__起きろ()

__wakeup() の使用目的は、シリアル化中に失われた可能性のあるデータベース接続を再確立し、その他の再初期化タスクを実行することです。

json_encode() について

  1. 魔法のメソッド __wakeup、__sleep がないため、制御が少なくなります
  2. プライベート プロパティをシリアル化しません。
  3. オブジェクトは常に stdClass として保存されます
  4. Json_encode はシリアライズよりも高速です

何を選択するかはあなた次第ですが、データベース接続などを使用したより高度なクラスの場合は、serialize() をお勧めします

于 2013-07-05T13:06:09.950 に答える