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

时间:2018-09-20 15:13:50

标签: symfony symfony-forms

在我的SF应用程序上,我具有“常规”表单(在控制器中使用formType生成)。

比方说,user1编辑formA,并且需要几分钟的时间来填写它。 在此期间,user2还编辑formA。 您可以猜到,最后一个点击“提交”的用户将获胜,而另一个则失去了他填写的所有内容。

如何防止这种情况发生?并非(由同一用户)多次提交。

我不知道是否有可能以及如何最好地实现它,但是我的猜测是添加一些“锁定”机制。

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

将@Version添加到实体的表单中的字段中就足够了,SF负责其余的工作吗?

我希望当user2尝试打开表单时,我可以发送消息:“对不起,user1已经完成了表单” 。我不希望user2仅在他单击“提交”时才松开他所有的填充。

谢谢。

2 个答案:

答案 0 :(得分:1)

框架并未提供您要实现的目标。

您可以利用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,这样,如果用户不提交表单,则锁仍被释放。 由于您仍然希望获得锁的用户能够提交表单,因此资源名称应包含例如用户标识符。

答案 1 :(得分:0)

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

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

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

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

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