如何更新doctrine对象类型字段

时间:2015-05-12 14:07:24

标签: php symfony doctrine-orm

我有一个实体用户,它实现了AdvancedUserInterface。该实体具有UserProperties类的字段属性,它被映射为对象类型。

我的实体:

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;
}

如果数据库中的属性值为 null ,并且我对设置属性的实体对象进行了一些更改 - 它工作正常。但是,如果我对数据库进行了一些更改并且属性字段为非null(已存在序列化的UserProperties对象) - 则不会保存更改(但是用户实体上的所有其他更改都是)。

我做错了什么?

2 个答案:

答案 0 :(得分:6)

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)。

但是,最后一个会要求你更改对象的所有setter并实际实现通知机制(如Doctrine docs所示),所以当我的代码中弹出这个问题时,我只是重新创建了存储的对象(这是我的第一个)建议,因为它很简单)。

但我确实认为这是一种意想不到的行为,所以我在Doctrine问题跟踪器中打开了一个票据/问题,所以至少有一个文档会对此发出警告。

答案 1 :(得分:6)

问题在于Doctrine不检查序列化对象的值是否已更改,它只检查对象是否相同(相同的内存指针)。

如果您在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();