2015-05-12 7 views
5

Possiedo un utente entità doctrine, che implementa AdvancedUserInterface. L'entità ha un campo proprietà della classe UserProperties, che viene mappato come un tipo di oggetto.Come aggiornare il campo tipo oggetto doctrine

mio Entity:

class User implements AdvancedUserInterface, \Serializable { 
<....> 
    /** 
    * @var UserProperties 
    * 
    * @ORM\Column(name="properties", type="object", nullable=true, options={"default":null}) 
    */ 
    private $properties; 
<....> 
} 

proprietà di classe:

class UserProperties { 
    public $isEmailVisible = false; 
    public $isNameVisible = false; 
} 

Se le proprietà valore nel database è nulla e faccio alcune modifiche al impostando le proprietà oggetto entità - sta funzionando bene. Ma se applico alcune modifiche al database e il campo delle proprietà NON è nullo (esiste già un oggetto UserProperties serializzato) - le modifiche non vengono salvate (ma tutte le altre modifiche sull'entità Utente sono).

Cosa faccio di sbagliato?

risposta

5

Il criterio di tracciamento di Doctrine verifica se un oggetto è stato modificato o meno, nel tuo caso - classe User. Tuttavia, quando si verifica se $this->properties è stato modificato tutto ciò che Doctrine fa è controllare se punta ancora allo stesso oggetto in memoria (!).

Se si vuole forzare l'aggiornamento oggetto memorizzato, è possibile copiare tutte le sue proprietà in una nuova istanza di oggetto (new UserProperties e poi riassegnare a $this->properties), clonarlo, o cambiare Dottrina monitoraggio della politica per NOTIFY (vedi http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html).

Ultimo, tuttavia, richiederà di modificare tutti i setter dell'oggetto e di implementare effettivamente il meccanismo di notifica (come mostrato in Doctrine docs), quindi quando questo problema è comparso nel mio codice, ho appena ricreato l'oggetto memorizzato (che è il mio primo suggerimento, in quanto è semplice).

Penso tuttavia che si tratti di un comportamento imprevisto, quindi aprirò un ticket/problema nel tracker dei problemi di Doctrine, in modo che almeno una documentazione avvisi su questo.

5

Problema: Doctrine non controlla se i valori dell'oggetto serializzato sono cambiati, controlla solo se l'oggetto è lo stesso (stesso puntatore di memoria).

Se si lavora con il serializzatore di oggetti in Doctrine è necessario creare sempre una nuova istanza dell'oggetto per salvarlo.

I.e.

$user = $form->getData(); 

$properties = new UserProperties(); 
$properties->setProperty1($oldValue1); 
$properties->setProperty2($newValue2); 
... 
$user->setProperties($properties); 

$em->persist($properties); 
$em->flush(); 

Ovviamente dovresti essere in grado di creare una copia dell'oggetto e assegnare solo i valori modificati.

$properties = clone $user->getProperties(); 
$properties->setProperty1($newValue); 

$em->persist($properties); 
$em->flush();