如何强制 Doctrine 更新数组类型字段? [英] How to force Doctrine to update array type fields?

查看:15
本文介绍了如何强制 Doctrine 更新数组类型字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有数组类型字段的 Doctrine 实体:

I have a Doctrine entity with array type field:

/**
 * @ORM\Table()
 */
class MyEntity
{
    (...)

    /**
     * @var array $items
     * 
     * @ORM\Column( type="array" ) 
     */
    private $items;

    /**
     * @param SomeItem $item 
     */
    public function addItem(SomeItem $item)
    {
        $this->items[] = $item;
    }

    (...)
}

如果我向数组中添加元素,此代码可以正常工作:

If I add element to the array, this code works properly:

$myEntityObject->addItems(new SomeItem()); 
$EntityManager->persist($myEntityObject);
$EntityManager->flush();

$myEntityObject 以正确的数据保存到数据库中(数组被序列化,查询数据库时反序列化).

$myEntityObject is saved to the database with correct data (array is serialized, and deserialized when querying database).

不幸的是,当我更改数组中的一个对象而不更改该数组的大小时,如果我尝试将更改保存到数据库,Doctrine 不会执行任何操作.

Unfortunately, when I change one of the object inside array without changing size of that array, Doctrine does nothing if I'm trying to save changes to the database.

$items = $myEntityObject->getItems();
$items[0]->setSomething(123);
$myEntityObject->setItems($items);
$EntityManager->persist($myEntityObject);
$EntityManager->flush();
print_r($myEntityObject);

尽管在该代码的最后一行 print_r 显示了更改的对象数据,但如果数组大小没有改变,Doctrine 并不知道数组内部发生了什么变化.有什么方法可以强制 Doctrine 保存在该领域所做的更改(或轻轻通知它该领域需要保存的更改)?

Although, print_r in the last line of that code displays changed object's data, Doctrine doesn't know that something was changed inside the array if array size didn't changed. Is there any way to force Doctrine to save changes made in that field (or gently inform it about changes in that field that needs to be saved) ?

刚刚在文档中找到了解决我的问题的方法:

Just found in documentation a way to solve my issue:

http://docs.doctrine-project.org/en/latest/reference/change-tracking-policies.html

它需要对代码进行大量更改,但它有效.有人知道如何为其他字段保留默认跟踪策略并仅对存储数组的字段使用 NotifyPropertyChanged 吗?

It requires a lot of changes in the code, but it works. Does someone know how to preserve default tracking policy for other fields and use NotifyPropertyChanged just for the field that stores array?

推荐答案

Doctrine 使用相同的运算符 (===) 来比较新旧值之间的变化.在具有不同数据的同一对象(或对象数组)上使用的运算符始终返回 true.还有一种方法可以解决这个问题,你可以克隆一个需要改变的对象.

Doctrine uses identical operator (===) to compare changes between old and new values. The operator used on the same object (or array of objects) with different data always return true. There is the other way to solve this issue, you can clone an object that needs to be changed.

$items = $myEntityObject->getItems();
$items[0] = clone $items[0];
$items[0]->setSomething(123);
$myEntityObject->setItems($items);

// ...

或者改变setItems()方法(我们只需要克隆一个对象来持久化整个数组)

Or change the setItems() method (We need to clone only one object to persist the whole array)

public function setItems(array $items) 
{
    if (!empty($items) && $items === $this->items) {
        reset($items);
        $items[key($items)] = clone current($items);
    }
    $this->items = $items;
}

关于第二个问题:

有人知道如何为其他字段保留默认跟踪策略并仅对存储数组的字段使用 NotifyPropertyChanged 吗?

Does someone know how to preserve default tracking policy for other fields and use NotifyPropertyChanged just for the field that stores array?

您不能只为一个字段设置跟踪策略.

You cannot set tracking policy just for a one field.

这篇关于如何强制 Doctrine 更新数组类型字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆