Symfony 2:如何防止多个用户同时编辑同一个表单?

Symfony 2 : How to prevent multiple user editing the same form at the same time?

在我的 SF 应用程序中,我有 "regular" 表单(在控制器中使用 formType 生成)。

假设用户 1 编辑了表单 A,并且需要几分钟来填写它。 在那段时间里,user2也编辑了formA。 你可以猜到,最后一个点击提交的用户获胜,另一个输掉他填写的所有内容。

我怎样才能防止这种情况发生?这不是多次提交(由同一用户)的情况。

我不知道这是否可行以及如何最好地实现它,但我的猜测是添加一些 "lock" 机制。

我读过https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html#locking-support

将@Version 添加到我的表单实体中的字段并且 SF 负责其余部分是否就足够了?

我希望当 user2 尝试打开表单时,我可以发送消息:"Sorry, user1 is already completing the form"。我不希望 user2 只有在他点击提交时才丢失他填写的所有内容。

谢谢。

框架没有立即提供您想要实现的目标。

您可以利用 Lock Component 或自己实施类似的解决方案。

// Symfony\Component\Lock\Factory $factory

$lock = $factory->createLock('your-amazing-form-USER-ID');

if (!$lock->acquire()) {
    // Sorry, user1 is already completing the form
    // throw exception or render a template for example
}

// Do what you need to show the form.

// Form is submitted and valid? Do what you need and release the lock.
if ($form->submited()) {
    // Save to database
    $lock->release();
}

一个好主意是给锁一个 TTL,这样如果用户不提交表单,锁仍然会被释放。 由于您仍然希望获得锁定的用户能够提交表单,因此资源名称应包含例如用户标识符。

显然,您可以使用锁,这样一次只有一个用户可以访问一个表单,但是正如评论中所述,您必须小心您的锁被释放,否则没有人可以访问表单直到 user1 完成。

这个超时机制也是一个问题,如果你设置得太短,你会陷入同样的​​问题,如果设置太长,你的用户会卡住。

您仍然可以设置更短的锁,并放置一些客户端脚本在锁过期时警告用户,但这又需要更多的工作。

另一方面,您可以考虑一种允许所有用户访问表单的机制,并且第一个提交的人保存他的数据,然后有一条消息告诉他数据已更新.这可以实现,而不是通过您正在寻找的 @Version,而只需添加一个 update date 字段即可。

对于此字段,您只需将此 update date 添加为隐藏字段,当用户提交表单时,您将提交字段的值与实体上的值进行比较,如果两个值不一致'匹配,您警告后续用户实体已在其间更新的事实。