Как обновить поле Тип объекта doctrine
У меня есть пользователь сущности doctrine, который реализует AdvancedUserInterface. Сущность имеет поле свойства класса UserProperties, который отображается как тип объекта.
Мои Сущности:
class User implements AdvancedUserInterface, Serializable {
<....>
/**
* @var UserProperties
*
* @ORMColumn(name="properties", type="object", nullable=true, options={"default":null})
*/
private $properties;
<....>
}
Properties класс:
class UserProperties {
public $isEmailVisible = false;
public $isNameVisible = false;
}
Если свойства значение в базе данных null и я делаю некоторые изменения в объекте сущности, устанавливая свойства-он работает нормально. Но если я внесу некоторые изменения в база данных и поле свойств не имеют значения null (уже существует сериализованный объект UserProperties) - изменения не сохраняются (но все остальные изменения в сущности пользователя).
что я делаю не так?
2 ответов
политика отслеживания доктрины проверяет, изменился ли объект, в вашем случае - User
класса. Однако, при проверке, если $this->properties
изменил все доктрины, это проверить, указывает ли он на тот же объект в памяти (!).
если вы хотите заставить его обновить сохраненный объект, вы можете скопировать все его свойства в новый экземпляр объекта (new UserProperties
а затем переназначить его на $this->properties
), клонировать его или изменить политику отслеживания доктрины на NOTIFY
(см. http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html).
последний, однако, потребует от вас изменить все сеттеры объекта и фактически реализовать механизм уведомления (как показано в Doctrine docs), поэтому, когда эта проблема появилась в моем коде, я просто воссоздал сохраненный объект (что является моим первым предложением, так как это просто).
Я думаю, однако, что это своего рода неожиданное поведение, поэтому я бы откройте тикет / проблему в Doctrine issue tracker, чтобы по крайней мере документация предупреждала об этом.
проблема здесь в том, что доктрина не проверяет, изменились ли значения сериализованного объекта, она проверяет только, является ли объект тем же самым (тот же указатель памяти).
Если вы работаете с сериализатором объектов в Doctrine, вам нужно всегда создавать новый экземпляр объекта для его сохранения.
т. е.
$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();