在我的SF应用程序上,我具有“常规”表单(在控制器中使用formType生成)。
比方说,user1编辑formA,并且需要几分钟的时间来填写它。 在此期间,user2还编辑formA。 您可以猜到,最后一个点击“提交”的用户将获胜,而另一个则失去了他填写的所有内容。
如何防止这种情况发生?并非(由同一用户)多次提交。
我不知道是否有可能以及如何最好地实现它,但是我的猜测是添加一些“锁定”机制。
将@Version添加到实体的表单中的字段中就足够了,SF负责其余的工作吗?
我希望当user2尝试打开表单时,我可以发送消息:“对不起,user1已经完成了表单” 。我不希望user2仅在他单击“提交”时才松开他所有的填充。
谢谢。
答案 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
添加为隐藏字段,当用户提交表单时,您将提交字段的值与实体上的值进行比较,如果这两个值不匹配匹配,您警告后续用户实体已在两者之间更新的事实。