2013-07-05 3 views
6

In PHP sto attraversando un periodo difficile utilizzando serialize/unserialize su una vasta gamma di oggetti (100000+ oggetti). Questi oggetti possono essere di molti tipi diversi, ma sono tutti discendenti di una classe base.PHP: array di oggetti - serialize vs json_encode - alternative?

In qualche modo quando uso unserialize sulla matrice di oggetti circa lo 0,001% degli oggetti vengono generati in modo errato! Al suo posto viene invece generato un oggetto completamente diverso. Questo non succede casualmente, ma ogni volta con gli stessi oggetti. Ma se cambio l'ordine dell'array, succede con oggetti diversi, quindi questo mi sembra un bug.

Sono passato a json_encode/json_decode, ma ho trovato che questo utilizza sempre stdClass come classe dell'oggetto. Ho risolto questo includendo il nome di classe di ogni oggetto come una proprietà, e quindi uso questa proprietà per costruire un nuovo oggetto, ma questa soluzione non è molto elegante.

L'utilizzo di var_export con eval funziona correttamente ma è circa 3 volte più lento rispetto agli altri metodi e utilizza molta più memoria.

Ora le mie domande sono:

  • che cosa potrebbe causare il bug oggetti/sbagliate che vengono creati con unserialize?
  • c'è un modo migliore per utilizzare json_decode con una matrice di oggetti, in modo che le classi siano in qualche modo memorizzate all'interno di JSON automaticamente?
  • c'è forse anche un altro metodo per leggere/scrivere una vasta gamma di oggetti in PHP?

UPDATE

sto cominciando a credere che ci deve essere qualcosa di strano con i miei array di dati, perché con msgpack_serialize (estensione php, alternativa al serialize) ottengo lo stesso tipo di errori (ma stranamente, non, gli stessi oggetti sono stati generati in modo errato!).

UPDATE 2

trovato una soluzione: invece di fare serialize sull'intera matrice, lo faccio su ogni oggetto ora, prima serialize e poi base64_encode e poi memorizzare ogni oggetto serializzato come una riga separata in un file di testo. In questo modo posso generare l'intera serie di oggetti e quindi iterare ogni oggetto usando file() con unserialize e base64_decode: niente più errori!

+0

quali errori vengono visualizzati? – Robert

+0

in qualche modo ALCUNI degli oggetti generati con unserialize, sono in realtà un oggetto completamente diverso che si trova anche nell'array, ma che ha quindi generato TWICE. Quindi sembra che ci sia qualcosa che non va con alcuni dei puntatori interni agli oggetti ... – Dylan

+0

Controlla la mia risposta Dylan serialize() è migliore per gli oggetti di grandi dimensioni json_encode è migliore per gli oggetti che non hanno risorse e non ti interessa se loro " sveglia "correttamente. – Robert

risposta

3

Con le funzioni serialize/unserialize sono collegati 2 metodi magici.

__sleep()

serialize() controlla se la classe ha una funzione con il nome magico __sleep(). In tal caso, tale funzione viene eseguita prima di qualsiasi serializzazione. Può pulire l'oggetto e deve restituire un array con i nomi di tutte le variabili dell'oggetto che deve essere serializzato. Se il metodo non restituisce nulla, NULL viene serializzato e viene emesso E_NOTICE.

Con sleep è possibile controllare meglio la serializzazione, è possibile passare le variabili che possono essere serializzate e pulire le risorse che possono interferire con la seralizzazione.

Quando unserialize è chiamato poi l'altra funzione è da citare

__wakeup()

L'uso previsto __wakeup() è quello di ristabilire le connessioni ai database che possono essere stati persi durante la serializzazione ed eseguire altre reinizializzazione compiti.

Chi json_encode()

  1. Non ha metodi magici __wakeup, __sleep in modo da avere meno controllo
  2. Non serializzare proprietà private
  3. oggetti sono sempre memorizzati come stdClass
  4. json_encode è più veloce di serializzare

Dipende da te ciò che scegli, ma per le classi più avanzate con connessione db, ecc. Vorrei suggerire serialize()