ArrayCollection项目的更改已完成,但未持久保存在数据库中

时间:2018-07-20 19:23:50

标签: php symfony doctrine-orm symfony-3.4

简介

所以,我有一个由学说监视的实体存在
我还有另一种决定,这是教义所不予关注的。

存在实体具有属性 $ decisions ,其类型为ArrayCollection,并且包含0到n个 Decision 实体。

由于我没有存储ArrayCollection中包含的每个 Decision 对象,因此我将属性 $ decision 键入Doctrine Array,到目前为止一切正常。 / p>

我可以从数据库中获取整个 Presence 对象,它包含我添加到其中的每个 Decision 对象。

问题

当我编辑 Presence 对象的ArrayCollection中存在的一个 Decision 对象时,例如:

    foreach($Presence->getDecisions() as $decision) {
        $decision->setMorning($value);
    }

修改是在本地应用的,当我输入dump($Presence);

时可以看到它们
Presence {#2354 ▼
  #id: 8
  #decisions: ArrayCollection {#1409 ▼
    -elements: array:6 [▼
      0 => Decision {#1408 ▼
        #token_id: "005867b2915438c03383bb831d87c26346c586d6ecd46b735c7a23b4fabb682a8ac34a90ea3d53cc55c2209deaa83337abeb2b98ded43967fcfb0f4d04d5ada6"
        #date: DateTime @1531692000 {#1407 ▶}
        #morning: -1
        #afternoon: 0
      }
      1 => Decision {#1406 ▶}
      2 => Decision {#1404 ▶}
      3 => Decision {#1402 ▶}
      4 => Decision {#1400 ▶}
      5 => Decision {#1398 ▶}
    ]
  }
  #last_edit_date: DateTime @1532109183 {#2454 ▼
    date: 2018-07-20 19:53:03.062940 Europe/Berlin (+02:00)
  }
  #user: User {#1393 ▶}
}

在此dump()上,您可以看到属性#morning: -1是setter调用的结果。

但是当我尝试使用$this->entityManager->flush();刷新更改时,尚未修改ArrayCollection。

起初,我认为这是更改检测的问题,因此我在我的 Presence 实体上添加了一个#last_edit_date DateTime字段。
有趣的是,刷新时此属性可以很好地更新。

由于某些原因,ArrayCollection似乎不会更新。

更新

要在此处补充我的信息,请参见其他信息:

控制器中的完整方法

/**
* @Route(name="edit_decision", path="/edit-decision/{tokenDate}/{dayPart}/{newValue}")
*/
public function EditDecisionAction(Request $request)
{
    $token = $request->get('tokenDate');
    $dayPart = $request->get('dayPart');
    $newValue = intval($request->get('newValue'));

    $myPresence = $this->em->getRepository('AppBundle:Presence')->findOneBy([
        'user' => $this->connectedUser
    ]);

    /** @var ArrayCollection $decisionCollection */
    $decisionCollection = $myPresence->getDecisions();

    $found = FALSE;

    /** @var Decision $decision */
    foreach ($decisionCollection as $decision) {
        if ($decision->getTokenId() == $token) {

            $found = TRUE;

            if ($dayPart === 'morning') {
                $decision->setMorning($newValue);
            }elseif ($dayPart === 'afternoon') {
                $decision->setAfternoon($newValue);
            }
            break;
        }
    }

    if (!$found) {
        throw $this->createNotFoundException();
    }

    // I set a new Date to trigger a modification on the Presence Entity : It works
    $myPresence->setLastEditDate(new \DateTime());

    // Here is the dump that you can see above
    dump($myPresence);

    $this->em->flush();

    try{
        $this->em->flush();
        return $this->json([
            'status' => TRUE
        ]);
    }catch (\Exception $exception) {
        return $this->json([
            'status' => FALSE
        ]);
    }
}

包含ArrayCollection的属性:

/**
 * Doctrine Type Array
 *
 * @ORM\Column(type="array", nullable=true)
 */
 protected $decisions;

欢迎任何帮助甚至提示! 谢谢:)

更新2

由于这篇文章,我可能找到了解决方法:
How to force Doctrine to update array type fields?

问题来自存储我的对象所依据的学说数组类型:

  

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

更新3

Nope仍然不能持久保存对ArrayCollection的项目所做的更改。 尝试克隆:添加:删除旧的,我们将检查会发生什么。

1 个答案:

答案 0 :(得分:0)

最终更新

好的,所以我终于可以使用技巧了。

主要问题是教义更改对Array类型的检测行为。

如上所述,原则是:Array ===用于检查是否要进行更改的数组。 之所以有点奇怪,是因为当您从ArrayCollection中添加或删除一个元素时,对于Doctrine而言,该集合仍等效于先前状态。 应该有一种方法可以像Java中那样测试2个对象之间的等效性。equals可以消除这些歧义。

无论如何我要解决它:
我将收藏集存储到初始状态:

$decisionCollection = $myPresence->getDecisions();

我放置了二传手并相应地修改了我的收藏集:

foreach ($myPresence->getDecisions() as $key => $decision) {
    if ($decision->getTokenId() == $token) {

        if ($dayPart === 'morning') {
            $decision->setMorning($newValue);
        } elseif ($dayPart === 'afternoon') {
            $decision->setAfternoon($newValue);
        }

        break;
    }
}

然后是技巧:

$myPresence->unsetDecisions();
$this->em->flush();

我完全取消了我的收藏集($ this-> collection = NULL)并第一次刷新。
由于数组!== NULL,它将触发更新
然后,我将集合与包含集合对象的更新集合一起设置:

$myPresence->setDecisions($decisionCollection);
$myPresence->setLastEditDate(new \DateTime());

最后一次刷新以保留新更改。

感谢大家的时间和评论!