Serializzare opzioni utente (Zend_Auth::getIstance()->getIdentity()->userOptions

Nella tabella Users che contiene i dati per l'autenticazione ho inserito un campo userOptions nel quale voglio conservare dei dati in un oggetto.

Esempio di accesso ai dati:

$user = Zend_Auth::getIstance()->getIdentity();
$userData = unserialize($user->userData);
$lastImages = $userData->lastImages;

Oppure in scrittura:

$userData->lastImages = array(12, 24, 39);
// metodo che si occupa della serializzazione di un clone da salvare sul database.
$userData->saveToDb();

Ma non so come creare l'ogetto userData, in particolare non voglio dover esplicitare ogni dato in esso contenuto.

In giro non ho trovato indicazioni utili e non so da dove partire.

Mi aiutate?

inviato 8 anni fa
arjuna
modificato 8 anni fa
Andrea Turso
Andrea Turso
86
X 0 X

Non capisco questa istruzione:

$userData = unserialize($user->userData);

Perché "unserializzi" $user->userData ?

risposto 8 anni fa
Gianni Tomasicchio
X 0 X

perchè userData è il campo della tabella user che conterrà l'oggetto serializzato quindi si assume che il contenuto di userData sia una serializzazione.

risposto 8 anni fa
arjuna
X 0 X

Fammi capire bene:

la tabella utenti è formata in questo modo:

<id, username, email, userdata>

Giusto?

Secondo me potresti provare a seguire questo procedimento:

All'atto del login con il metodo getResultRowObject ottieni la riga del record che ha soddisfatto la condizione di login - in poche parole la riga dell'utente che si è loggato - e poi fai questo:

//$authAdapter e' l'adattatore che hai utilizzato per specializzare Zend_Auth, hai un riferimento all'istanza, vero?
$utente = $authAdapter->getResultRowObject();
//print_r($authAdapter->getResultRowObject());
$utente = unserialize($utente['userData']);

Comunque non capisco la necessità del tuo campo userData

Ciao :bye:

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
X 0 X

UserData deve contenere alcuni parametri dell'utente come le ultime azioni effettuate, le ultime foto selezionate, e altre cose per le quali non credo sia utile usare una tabella apposita per contenere i dati.

Creando un oggetto posso stipare al suo interno quel che mi pare senza dover toccare la struttura del database.

Il punto non è tanto recuperare i dati quanto scriverli e serializzarli... stavo pensando di usare Zend_Registry e salvarne una serializzazione in user data ma non ho ancora provato.

risposto 8 anni fa
arjuna
X 0 X

Guarda questo codice:

<?php
include 'Zend/Db.php';
include 'Zend/Auth.php';
include 'Zend/Auth/Adapter/DbTable.php';

$db = Zend_Db::factory('pdo_mysql', array('...'));
$adapter = new Zend_Auth_Adapter_DbTable($db, 'tabellaUtenti', 'nomeUtente', 'passwordUtente', 'sha1(?)');

$adapter->setIdentity('***username***')->setCredential('***password***');

$user = $adapter->authenticate();
var_dump($user->getIdentity(), unserialize($adapter->getResultRowObject()->userData));

Dovrebbe darti lo spunto necessario. Comunque non capisco da dove nasca la tua necessità di utilizzare un'istanza del registro (Zend_Registry) per mantenere la serializzazione.

Credo che l'approccio che dovresti seguire sia questo:

  • Crei una classe contenitore per le preferenze dell'utente.
  • Quando devi creare per la prima volta le preferenze dell'utente:

           

    • crei un'istanza della classe e la configuri
    • la serializzi con con serialize(string $value)
    • la salvi nel database nel record associato all'utente.
       
  • Quando devi aggiornare le preferenze dell'utente (e.g. quando l'utente modifica il profilo o compie un'azione che va registrata nell'oggetto delle preferenze):

           

    • Estrai la stringa dell'oggetto serializzato
    • La deserializzi con unserialize(string $str), ottenendo così un'istanza dell'oggetto originale
    • Modifichi l'istanza in modo programmatico in base ai nuovi valori (in pratica la riconfiguri)
    • La riserializzi, sempre con serialize
    • La salvi nuovamente nel database, nel record associato all'utente
       

Nel caso ti servisse, onde evitare troppe richieste al database server, rendere persistente l'istanza delle preferenze ti basterebbe utilizzare Zend_Session per memorizzare l'istanza serializzata (proprio come faresti con il database) dell'oggetto contenente le preferenze dell'utente.

:bye:

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
modificato 8 anni fa
X 0 X

Ti ringrazio per l'attenzione che mi dedichi e mi dispiace non riuscire a spiegarmi come vorrei.

Il codice da te proposto è la base da cui si parte.

Quello che mi manca è capire come strutturare la classe per le prefenze e come e quando instanziarla.

Voglio estrarre le preferenze quando l'utente fa login.

Queste vanno memorizzate nel front controller per essere ripescate quando servono e aggiornate quando occorre.

Per questo avevo pensato al registro di zend, Zend_session mi permette di portare in giro le preferenze istanziate ma non mi permette di salvarle se non su un cookie, che è inaffidabile per me.

Sto cercando di automatizzare tutti i processi basilari per l'interazione sito->utente utente->sito

risposto 8 anni fa
arjuna
X 0 X

Dov'è il problema scusa? Allo stato attuale al codice che ti ho postato manca solo la parte della serializzazione e del salvataggio del record nel databse, una query in pratica.

Per la classe delle preferenze non hai pensato proprio a nulla? Basterebbe anche un array eh.

Guarda questo (pseudo)codice, dovrebbe darti un'idea più precisa di cosa fare:

//---- inserimento delle preferenze, quando viene registrato l'utente, è un'insert!
$preferences = array('option1' => 30, 'option2' => true, 'option3' => $value, 'option4' => 5);
$preferences = serialize($preferences);
$query = "insert into ... (... , `userData`) values (..., '{$preferences}') where ... and username={$username}";
$database->executeQuery($query);

//---- caricamento delle preferenze
$query = "select `userData` from ... where ... and username={$username}";
$preferences = $database->getResultRow($query);
$preferences = unserialize($preferences);
var_dump($preferences); 

//---- modifica delle preferenze
$preferences['option1'] = $newValue;
$preferences['option2'] = false;

//---- salvataggio delle preferenze
$preferences = serialize($preferences);
$query = "update ... set `userData`='{$preferences}' where ... and username={$username}";
$database->executeQuery($query);

:bye:

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
modificato 8 anni fa
X 0 X

Tutto qui?

ed io che pensavo di dover fare chi sa che  :D

ora credo di avere tutto quello che mi serve per partire.

Grazie!

risposto 8 anni fa
arjuna
X 0 X

Ho notato una piccola incoerenza nel codice che ti ho postato.

Si trova nella prima query, quella per la registrazione del record dell'utente, dato che l'utente non esiste e si presume che la query debba creare il record dell'utente, la clausola where (where ... and username={$username}) quindi è superflua.

,Andrea

:bye:

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
modificato 8 anni fa
X 0 X

questi so dettagli, mi interessava sapere la procedura in generale... tnks a lot

risposto 8 anni fa
arjuna
X 0 X

Passi avanti, nuovi problemi.

Posto:

$user = Zend_Auth::getInstance()->getIdentity();

se faccio il dump di:

unserialize($user->userData);

ottengo il valore di userData relativo all'istanziamento dell'utente e non eventuali aggiornamenti effettuati sul database.

Mi spiego meglio.

Ipotiziamo che userData contenga l'array "preferiti" e che quando istanzio l'utente il contenuto di $user->userData['preferiti'] è vuoto.

Successivamente l'utente compie un azione che si tramuta in:

$user->userData['preferiti'] = $valori;
         
$pref = serialize($user->userData);
Zend_Db_Table::getDefaultAdapter()->update('utenti', array('userData'=>$pref), "username = '" . $this->_user->username. "'");

Così facendo il record del database è stato aggiornato ma non così il valore di $user->userData.

Se infatti richiamo il contenuto di $user->userData['preferiti'] mi restituisce sempre il valore iniziale.

Se invece faccio logout e poi di nuovo login, il valore è quello giusto.

L'approccio che uso è completamente sbagliato.

Da solo sarei in grado di inventarmi qualcosa che faccia funzionare il tutto ma non mi viene in mente nulla di performante.

Attualmente ho creato una classe:

class My_Controller_Action extends Zend_Controller_Action
{
   protected $_user;
   public function init()
   {
      $this->_user = Zend_Auth::getInstance()->getIdentity();
      // il controllo su _user serve nel caso in cui l'utente non sia loggato
      $this->_userPref = ($this->_user) ? serialize($this->_user->userData) : null;
      
      
   }
}

che uso per creare i miei controller.

Il controller usato fa più o meno così:

class Admin_TestController extends My_Controller_Action
{
   public function preferitiAction()
   {
      $this->_userPref['preferiti'] = $this->_getParam('id');
      $pref = serialize($this->_userPref);
      Zend_Db_Table::getDefaultAdapter()->update('utenti', array('userData'=>$pref), "username = '" . $this->_user->username. "'");
   }
}

Mi sembra di capire però che così faccio un lavoro enorme e poco performante.

Per altre tabelle sul database ci sono i Models relativi che mi permettono di fare cose come:

$foto = new Foto;

$foto->update('titolo', $foto->getAdapter()->quoteInto('id = ?', $id));

$foto->find($id);

Devo quindi creare un Model per gli utenti?

Che ne pensate?

risposto 8 anni fa
arjuna
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda