2015-05-12 3 views
5

У меня есть доктрина Entity User, которая реализует AdvancedUserInterface. Объект имеет поле свойства класса UserProperties, который отображается как тип объекта.Как обновить поле типа объекта доктрины

Мой Entity:

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

Свойства класса:

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

Если свойства значение в базе данных является нулевой и я сделать некоторые изменения в сущности объекта настройки свойств - он работает нормально. Но если я вношу некоторые изменения в базу данных, а поле свойств НЕ является нулевым (уже есть сериализованный объект UserProperties) - изменения не сохраняются (но все остальные изменения в сущности пользователя).

Что делать неправильно?

ответ

5

Политика отслеживания Doctrine проверяет, изменился или нет объект в вашем случае - User класс. Однако при проверке, изменилось ли значение $this->properties, Doctrine действительно проверяет, все ли он указывает на тот же объект в памяти (!).

Если вы хотите, чтобы заставить его обновить сохраненный объект, вы можете скопировать все это свойства нового экземпляра объекта (new UserProperties, а затем передать его $this->properties), клонировать его, или изменить доктрину отслеживания политики в NOTIFY (см http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html).

Последний, однако, потребует, чтобы вы изменили все сеттеры объекта и фактически реализовали механизм уведомления (как показано в документах Doctrine), поэтому, когда эта проблема возникла в моем коде, я просто воссоздал сохраненный объект (который является моим первое предложение, поскольку это просто).

Я действительно думаю, что это своеобразное непредвиденное поведение, поэтому я должен открыть билет/вопрос в трекере по проблеме Doctrine, чтобы, по крайней мере, об этом предупреждала документация.

5

Проблема заключается в том, что Doctrine не проверяет, изменились ли значения сериализованного объекта, он проверяет, является ли объект одним и тем же (тот же указатель памяти).

Если вы работаете с сериализатором объектов в Doctrine, вам нужно всегда создавать новый экземпляр объекта для его сохранения.

I.e.

$user = $form->getData(); 

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

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

Конечно, вы должны иметь возможность создать копию объекта и присвоить только измененные значения.

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

$em->persist($properties); 
$em->flush(); 
Смежные вопросы