4

データ オブジェクト (本質的には多次元配列) をバックエンド データベースに保持しようとするサーバー側の PHP コードがあります。このデータ オブジェクトは、元々、フレックス アプリケーションから送信された AMF アクションスクリプト オブジェクトとして入ってきます。後で使用するためにオブジェクト全体を永続化したいので、php シリアル化関数を使用し、データベース フィールドに入力できる単純な文字列にオブジェクトをエンコードしました。コードは次のようになります。

$serializedDataObject = base64_encode(serialize($objectInstance->myDataObject));

このオブジェクトを復活させて元に戻したいときは、逆を実行するだけです

$unserializedDatanObject = unserialize(base64_decode($serializedDataObject));

これまでのところ、これはうまく機能しているようです。しかし、私のphpスクリプトが失敗することがあります。シリアル化の段階で失敗していると思います。私の質問は、理論的に言えば、PHP のシリアライゼーションとエンコーディング プロセスが失敗する原因は何ですか? データ オブジェクト配列に特定の文字または種類のデータがあり、シリアライゼーションが失敗する可能性がありますか?

データ オブジェクトをシリアル化する前に、データ オブジェクトをマッサージする必要がありますか?

編集:

プロセスを明確にするために、このように機能します

AMF ベースの actionscript オブジェクトをサーバーに送信する Flex/Actionscript クライアント アプリがあります。PHP 側では、Zend AMF ライブラリを使用して AMF データを読み取ります。このオブジェクトは PHP で調べることができ、基本的に連想多次元配列のように見えます。この時点で、オブジェクトをシリアル化して Base 64 エンコードし、オブジェクトをエンコードされた文字列としてデータベースに保持できるようにします。

うまくいけば、これは理にかなっています。問題は断続的であり、一貫して再現するのは簡単ではありません。特定のエラー メッセージが表示された場合は、ここに投稿してさらに明確にします。しかし今のところ、さらにデバッグするのに役立つシリアライゼーションの限界は何かと思っていました。

4

6 に答える 6

5

リソースをシリアル化できないことが問題である可能性があります。この問題を回避する方法は、マジック メソッドを使用することです:__sleep__wakeup.

基本的に、シリアル化__sleepを呼び出すと関数が呼び出され、__wakeupシリアル化を解除するためのものなので、データベース接続だとします。スリープ()で接続を閉じ、接続文字列をどこかに(おそらく)保存し、ウェイクアップで再接続します。

于 2009-08-27T14:51:42.987 に答える
4

@Greg は、リソースをシリアル化できないという点で正しいです。

あなたのオブジェクトを「データオブジェクト」と表現していることを考えると、データベース接続リソースが含まれていると思いますか? (例$object->rs = mysql_connect(...);)。

その場合は、データ オブジェクトで関数__sleep()__wakeup()関数を使用することを検討してください (__sleep()はシリアル化の直前、シリアル化解除の直後に呼び出されます__wakeup())。

The __sleep() function should close any database or file resources while the __wakeup() function should reconnect to the database.

The PHP manual entry I linked above has an example of a class that manages a DB connection that is serializeable:

<?php
class Connection {
    protected $link;
    private $server, $username, $password, $db;

    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }

    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }

    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }

    public function __wakeup()
    {
        $this->connect();
    }
}
于 2009-08-27T14:50:55.517 に答える
3

ファイル ハンドルやデータベース接続などのリソースを適切にシリアル化できません。また、組み込みの PHP オブジェクトをシリアライズすることもできませんが、それが何をカバーするのか正確にはわかりません。

于 2009-08-27T14:34:17.807 に答える
3

php.net/bas64_decode では、大きな文字列がうまくデコードされないという言及があります。また、オブジェクトにサポートされていない文字形式が含まれていると、問題が発生する可能性があります。

  1. オブジェクトにサポートされていない文字形式がないことを確認してください
  2. シリアル化されているオブジェクトの大きさをログに記録してみてください
于 2009-08-27T14:34:45.840 に答える
1

これでトムと一緒に行かなくちゃ。php.net/serializeを引用するには:

シリアル化される値。serialize()は、resource-typeを除くすべてのタイプを処理します。それ自体への参照を含む配列をserialize()することもできます。シリアル化する配列/オブジェクト内の循環参照も保存されます。その他の参照はすべて失われます。

標準オブジェクトに関する限り、問題はないはずです。base64_encoding / decodeの後に取得したデータをログに記録し、次の行を使用してデータを確認します。

echo '<pre>'; print_r($decodedObject); echo '</pre>';
于 2009-08-27T14:46:36.240 に答える
1

シリアル化されたデータをデータベース内に保存していますか?もしそうなら、フィールドはデータを保持するのに十分な大きさですか?Base64エンコーディングでは、文字列の長さが約1.3倍になり、一部のDBシステムでは切り捨てられます。

于 2009-08-27T14:49:38.310 に答える