2012-10-30 6 views
8

こんにちは私はSessionHandlerや配列$ _SESSIONのようなクラスを使ってセッション内にオブジェクトを保存したり保存したりしたいと思います。オブジェクトを直列化すると可能ですが、そのオブジェクトのインスタンスが..私はそれをseralizing見てきました は可能ですが、私は保存したいオブジェクトをするPDOStatementによって作成された::はfetchObject()インスタンスクラスalthought私はこのエラーを取得する「ユーザー」である:PHPでセッションにオブジェクトを保存するにはどうしたらいいですか?

PDOException: You cannot serialize or unserialize PDO instances Why? It is not a PDO instance..

は申し訳ありませんが、私はスペイン語と私は非常によく英語を話せない... おかげで

+1

ショーはどのようにあなたは、それをシリアル化しようとしている例外から、あなたが声明をシリアライズしようとしているようです、それは結果ではありません。 –

+0

@ dev-null-dwellerによると'PDOStatement :: fetchObject'の結果をちょうど良いものにすることができます。 –

+0

オブジェクトがデータベースのものである場合、セッションでそれをシリアル化する理由は何ですか?ただDBからもう一度それをつかみなさい。セッションは可能な限り避けなければなりません。 –

答えて

14

PHPのネイティブ$_SESSIONセッションが透過的にシリアライズしUNS PHPのserialization protocolまたはSerializable interfaceをサポートするオブジェクトをerializeします。明示的にシリアライズする必要はありません。

PHPはresourcesをシリアル化できません。これは、PHPのコントロール外のステートフルなリソースに対するハンドルなのでです。このため、PDOまたはPDOStatementオブジェクトはシリアル化できません。

デフォルトでは、オブジェクトはすべてのプロパティ名と値を保存することによってシリアル化され、同じクラス(コンストラクタを呼び出さずに)を作成してシリアル化されたプロパティを直接設定することによって、 __sleep__wakeupのマジックメソッドを使用するか、Serializableインターフェイスを実装することで、オブジェクトのシリアル化動作をカスタマイズできます。しかし、両方ではありません! implements Serializableを使用すると、__sleep__wakeupは無視されます。

一つの重要な注意事項:オブジェクトのシリアル化を使用しているとき、あなたはあなたがアンシリアライズ(またはそれを読み込むことができオートローダーを持っている)の前にロードされたクラス定義を持っている必要があり、それが、そのオブジェクトのクラス定義と一致する必要がありますシリアル化されました。クラス定義は直列化されたデータには格納されません。今、あなたの新しいコード直列化オブジェクトにロードするとし

class Test { 
    public $version = 2; 
    private $def; 
    public function setDef ($def) { 
     $this->def = $def; 
    } 
} 

を:今、あなたはこの代わりのようになりTest 1日に変更想像

class Test { 
    public $version = 1; 
    protected $abc; 
    public function setAbc($abc) { 
     $this->abc = $abc; 
    } 
} 

$t = new Test(); 
$t->setAbc(123); 
$_SESSION['mytest'] = $t; 

たとえば次があるとしTestがバージョン1のとき:

$t = $_SESSION['mytest']; // this was stored yesterday, when Test was version 1 

var_dump($t) 

あなたはこれを取得します:

object(Test)#1 (3) { 
    ["version"]=> 
    int(1) 
    ["def":"Test":private]=> 
    NULL 
    ["abc":protected]=> 
    int(123) 
} 

をさらに、古いメソッドを使用することはできません。

if ($t->version == 1) { // Check for class version 
    $t->setAbc(345); // "Fatal error: Call to undefined method Test::setAbc()" 
} 
+0

私の問題は解決しましたが、そのクラスでは、__constructor(これはMySQLに接続されています)でPDOオブジェクトを渡し、PDOオブジェクトにメンバー変数を設定しましたが、 "コンテナオブジェクト" __constructor関数を実行しないため、PDOオブジェクトであるメンバ変数は設定されません。 どうすれば解決できますか?ありがとう – Carlos

+3

これは答えに説明されています。オブジェクトは* * *初期化されていない*ために実行されません。必要な処理を行う '__wakeup()'または 'serializer'インターフェース' unserialize() 'を作成するか、' setPDO() 'メソッドを追加してPDOオブジェクトを手動で設定します。しかし、ボトムラインでは、**リソースを含むオブジェクトを直列化してはいけません**!別のクラスデザインを使用してください。 –

+0

ありがとう、私はsetPDOメソッドを追加するあなたの考えが好きです:) – Carlos

関連する問題