2012-10-30 10 views
8

Ciao Vorrei salvare o salvare un oggetto all'interno di una sessione, usando classi come SessionHandler o array $ _SESSION, ho visto che è possibile se serializzo l'oggetto, e non voglio perdere i metodi di tale istanza oggetto .. che ho visto seralizing è possibile ma gli oggetti che cosa voglio per memorizzare è stato creato da PDOStatement :: fetchObject() ma decorate la classe istanza è "utenti" ottengo questo errore:Come posso archiviare oggetti in una sessione in PHP?

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

Scusate lo spagnolo e non parlo molto bene .. Grazie

+1

Mostrare come stai cercando di serializzare esso, dal l'eccezione sembra che si sta cercando di serializzare dichiarazione , non è il risultato. –

+0

Cosa dice @ dev-null-dweller. Posso serializzare il risultato di 'PDOStatement :: fetchObject' bene. –

+0

Se l'oggetto proviene dal database, perché dovresti serializzarlo in una sessione? Prendilo di nuovo dal DB. Le sessioni dovrebbero essere evitate il più possibile. –

risposta

14

sessioni native di PHP $_SESSION in modo trasparente serializza e uns erializzare oggetti che supportano il serialization protocol di PHP o lo Serializable interface. Non è necessario serializzarli esplicitamente.

PHP non può serializzare resources perché si tratta di handle per alcune risorse stateful al di fuori del controllo di PHP. Questo è il motivo per cui non è possibile serializzare gli oggetti PDO o PDOStatement.

Per impostazione predefinita, un oggetto viene serializzato salvando tutti i nomi di proprietà e valori e non serializzati creando un oggetto con la stessa classe (senza richiamare il costruttore) e impostando direttamente le proprietà serializzate. È possibile personalizzare il comportamento di serializzazione per gli oggetti utilizzando i metodi magici __sleep e __wakeup o implementando l'interfaccia Serializable. Ma non entrambi! Se si utilizza implements Serializable, __sleep e __wakeup vengono ignorati.

Una nota importante: quando si utilizzano serializzazione degli oggetti, si necessario avere la definizione di classe caricato prima di unserialize (o avere un caricatore automatico che può caricarlo) e necessario corrispondere alla definizione della classe dell'oggetto che è stato serializzato. Le definizioni di classe non sono memorizzate nei dati serializzati.

Per esempio si supponga di avere il seguente:

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

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

Ora immaginate si cambia Test un giorno per essere come questo, invece:

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

Ora supponiamo che si carica nel nuovo codice di un oggetto serializzato quando Test era alla versione 1:

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

var_dump($t) 

Otterrete questo:

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

Inoltre, non è possibile utilizzare i vecchi metodi:

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

Grazie risolto il mio problema, ma ho un nuovo problema, su quella classe ho passato l'oggetto PDO in __constructor (che è connesso a MySQL) e ho impostato una variabile membro su Oggetto PDO, ma quando ho unserialize "oggetto contenitore" non esegue la funzione __constructor, quindi la variabile membro che è un oggetto PDO non verrà impostata .. Come posso risolverlo? Grazie – Carlos

+3

Questo è spiegato nella risposta. I costruttori non vengono eseguiti perché l'oggetto è * ripristinato * non * inizializzato *. Crea un metodo '__wakeup()' o 'Serializer' 'unserialize()' che fa quello che vuoi, oppure aggiungi un metodo 'setPDO()' e imposta manualmente l'oggetto PDO. In conclusione, però, ** non dovresti serializzare oggetti che contengono risorse **! Usa un design di classe diverso. –

+0

Grazie mille, mi piace la tua idea aggiungendo un metodo setPDO, hai ragione :) – Carlos