我正在构建一个应用程序,用户可以在其中编辑一些数据,然后会看到一个屏幕,在那里他可以确认(并评论)自己的编辑。
在确认表单中,我显示对实体所做的更改。这适用于"正常"字段。以下是一些用于检查单个字段的代码:
// create $form
// bind $form
if ($form->isValid() {
$data = $form->getData();
// example, get changes of a "normal" field
if ($data['color'] != $entity->getColor()) {
// do something with changes
}
}
但我不能对关系做同样的事情(例如ManyToMany with Users):
if ($data['users'] != $entity->getUsers()
不起作用,因为$data['users']和$entity->getUsers()引用了同一个持久集合。可以调用此函数来查看是否有更改:
if ($data['users']->isDirty())
但我们不可能看到发生了什么变化。
上面的第二个问题是,如果所有项目都从持久集合中删除,Doctrine不会将其标记为"已更改"(isDirty()=true),因此我无法捕捉到用户从表单中的实体中删除所有"用户"的具体更改。
请注意,代码都有效,我唯一的问题是无法查看/处理在确认步骤中所做的更改。
Doctrine'ORM'PersistentCollection
具有内部API(公共)方法getSnapshot
、getDeleteDiff
、getInsertDiff
,这些方法可在Doctrine'ORM'UnitOfWork
的生命周期事件期间使用。例如,您可以在onFlush
期间检查持久集合的insertdiff。
这样解决:
1) 要获得将直接对实体进行的更改,请使用以下内容:
// create form
// bind form
// form isValid()
$uow = $em->getUnitOfWork();
$uow->computeChangeSets();
$changeset = $uow->getEntityChangeSet($entity);
print_r($changeset);
2a)要更改关系,请使用上面Lighthart的答案:
$oldUsers = $entity->getUsers()->toArray();
// bind form
// form isValid
$newUsers = $entity->getUsers()->toArray();
// compare $oldUsers and $newUsers
2b)在持久收集上使用这些方法来查找插入/删除:
$newUsers = $entity->getUsers();
$inserted = $newUsers->getDeleteDiff();
$deleted = $newUsers->getInsertDiff();
(2b)的唯一问题是,如果删除了所有用户,但没有添加任何用户,那么getDeleteDiff()为空,这似乎是一个Doctrine错误/特质
在绑定前将原始集合存储在变量中,然后在绑定后比较新集合。PHP有相当多的数组比较函数,$collection->toArray()可以很容易地将集合转换为本机数组;
例如:
// create form
$oldusers=$entity->getUsers()->toArray();
// bind form
if ($form->isValid() {
$data = $form->getData();
if ($data['users'] != $oldusers) {
// do something with changes
}
}