Как обновить поле Тип объекта 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();