Symfony 2 / Doctrine 2:对PersistentCollection进行更改

时间:2013-02-11 12:13:23

标签: php forms symfony doctrine-orm persistence

我正在构建一个应用程序,用户可以在其中编辑一些数据,然后会出现一个屏幕,用于确认(和评论)他的编辑。

在确认表单中,我显示对实体所做的更改。这适用于“普通”字段。以下是一些用于检查单个字段的代码:

// 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),因此我无法捕获用户所在的具体更改从表单中的实体中删除所有“用户”。

请注意,代码全部有效,我唯一的问题是我无法查看/处理在确认步骤中所做的更改。

3 个答案:

答案 0 :(得分:6)

Doctrine\ORM\PersistentCollection具有内部API(公共)方法getSnapshotgetDeleteDiffgetInsertDiff,可以在Doctrine\ORM\UnitOfWork的生命周期事件中使用。例如,您可以在onFlush期间检查持久集合的插入差异。

答案 1 :(得分:4)

解决这个问题:

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)在Persistent Collection上使用这些方法来查找插入/删除:

$newUsers = $entity->getUsers();
$inserted = $newUsers->getDeleteDiff();
$deleted  = $newUsers->getInsertDiff();

(2b)的唯一问题是如果删除了所有用户而没有添加任何用户,则getDeleteDiff()为空,这似乎是一个Doctrine bug / idiosyncrasy

答案 2 :(得分:0)

在绑定之前将原始集合存储在变量中,然后在绑定之后比较新集合。 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
    }
}