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

mog*_*man 6 php forms persistence symfony doctrine-orm

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

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

// 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
    }
}
Run Code Online (Sandbox Code Playgroud)

但我不能对关系做同样的事情(例如ManyToMany with Users):

    if ($data['users'] != $entity->getUsers()
Run Code Online (Sandbox Code Playgroud)

因为$ data ['users']和$ entity-> getUsers()引用相同的持久集合,所以不起作用.可以调用此函数来查看是否有更改:

    if ($data['users']->isDirty())
Run Code Online (Sandbox Code Playgroud)

但是不可能看到做了哪些改变.

上面的第二个问题是,如果从持久集合中删除所有项目,则Doctrine不会将其标记为"已更改"(isDirty()= true),因此我无法捕获用户删除所有内容的具体更改"用户"来自表单中的实体.

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

Ocr*_*ius 6

Doctrine\ORM\PersistentCollection已内部API(公开)的方法getSnapshot,getDeleteDiff,getInsertDiff可期间的生命周期事件中使用Doctrine\ORM\UnitOfWork.例如,您可以检查持久集合的插入差异onFlush.


mog*_*man 5

是这样解决的:

1) 要获得将直接对实体进行的更改,请使用以下命令:

// create form
// bind form
// form isValid()

$uow = $em->getUnitOfWork();
$uow->computeChangeSets();
$changeset = $uow->getEntityChangeSet($entity);
print_r($changeset);
Run Code Online (Sandbox Code Playgroud)

2a) 要更改关系,请使用上面 Lighthart 的答案:

$oldUsers = $entity->getUsers()->toArray();
// bind form
// form isValid
$newUsers = $entity->getUsers()->toArray();
// compare $oldUsers and $newUsers
Run Code Online (Sandbox Code Playgroud)

2b) 在 Persistent Collection 上使用这些方法来查找插入/删除:

$newUsers = $entity->getUsers();
$inserted = $newUsers->getDeleteDiff();
$deleted  = $newUsers->getInsertDiff();
Run Code Online (Sandbox Code Playgroud)

(2b) 的唯一问题是,如果所有用户都被删除并且没有添加,那么 getDeleteDiff() 是空的,这似乎是一个 Doctrine 错误/特质


Lig*_*art 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
    }
}
Run Code Online (Sandbox Code Playgroud)