我已经完成了使用CakePHP完成的预订申请,该申请涉及结账页面前的几个步骤。在这些步骤之间,我将信息存储在会话中。
工作原理是第1步要求他们填写信息。转到步骤2时,步骤1中的信息将保存到会话对象中。当他们继续进行其他步骤时,重复该过程。结账时,所有数据都会保存到数据库中。
如果用户在浏览器中打开一个应用程序实例,那么一切都很有效。但是,一旦他们在同一个浏览器中为同一个应用程序打开了另一个页面或另一个选项卡,就会出现问题。
假设他们在选项卡A和选项卡B中打开了两个应用程序实例。在选项卡A中,他们在步骤1中输入了详细信息,然后继续执行步骤2.然后用户在选项卡B中执行相同操作。
在用户结帐时的最后一步,标签A中的信息与标签B中的信息相同。
现在,我只能认为最好的方法是阻止用户在两个浏览器实例中打开相同的应用程序。
当他们尝试在标签B中打开另一个实例时,有没有办法检测并提示用户先在标签A中填写预订表单?
答案 0 :(得分:9)
1.同样的问题(和解决方案):https://sites.google.com/site/sarittechworld/track-client-windows
2.您可以通过POST或GET发送信息
答案 1 :(得分:2)
当然,您可以使用客户端轮询器脚本来实现此目的。在JavaScript中,您可以生成一个窗口ID,只要它保证是唯一的,它就可以是任何东西。让JS将Ajax调用者发送到服务器上的端点,该端点除了比较ID和会话之外什么都不做。在任何时候,如果你有两个不同的“windowID”值,你知道他们必须打开窗口进行同一个会话。
您可以将其作为会话中的数组存储在服务器端,或者甚至可以将其完全存储在cookie中的客户端。如果你选择这样做,你的客户端轮询器只会查看cookie值,如果它包含两个不同的值,则有些不对劲。 Cookie虽然不太理想,但因为它们会增加请求/响应周期的重量,并且您必须设置一种机制来在用户卸载页面时清除当前页面的值。
对于服务器端实现,您只需要发送当前windowID以及链接或发布,以便服务器可以从会话中清除windowID。这些都不能防止用户同时打开Firefox会话和Chrome会话。
答案 2 :(得分:2)
您可以在首次启动第1步时将会话标记为已启动。确保服务器端他们遵循正确的步骤(即他们在步骤1完成后不返回步骤1,除非他们专门点击链接这样做。)基本上,跟踪他们在服务器上的当前步骤并更新它如所须。如果用户做了意想不到的事情,你可以给他们重新开始的选项。
我想知道表单上带有时间戳的隐藏字段是否有帮助。虽然有点相同的想法。
警告:此过程可能会破坏浏览器后退按钮的本质。我讨厌让自己在我的一个项目中发生这种情况。
对于跨浏览器支持,您需要将其与用户帐户或持续存在的内容相关联。
答案 3 :(得分:0)
正如Benjamin指出的那样,您可以通过提供每个窗口ID来执行此操作,然后您可以根据每个请求向服务器报告。如果要启用多窗口用例,我认为这是最合理的方法。
我认为您不需要通过ajax轮询服务器来执行此操作。只要对服务器的每个请求都包含窗口ID,您就可以消除服务器端与请求关联的会话的歧义。这意味着您的服务器端代码必须更改为包含窗口ID作为会话的一部分。
然而,这种方法有严重的缺点。例如,如果用户同时关闭选项卡A和选项卡B,然后打开一个新的选项卡C ......会发生什么?他们应该重新连接哪组数据?
如果您需要阻止多个标签状态的混合,那么将用户限制为单个标签的方法听起来非常合理。
你可以通过本地存储,顺便说一句。如果您在客户端上生成随机ID并通过window.localStorage.setItem('window_id', <my_random_id_here>);
之类的调用将其推送到本地存储,那么您可以在页面加载时检查此值。如果页面加载时存在该值,则表明至少有一个其他窗口处于打开状态。您必须确保在页面卸载时删除此值,否则死会话可能会触发误报。