跨多个选项卡的父子导航


Parent-Child navigation across multiple tabs

请耐心听我解释,这是必要的。

系统背景:我正在为CMS的后端创建一个父->子导航系统。我这样构建URL:[domain.ext]/[moduleName]/[objectName]/[actionName]/[ID #1]/[ID #2]

解释的URL(例如example.com/PageManagement/Page/Modify/7/13):

  • moduleName :对象所属模块的名称(例如"PageManagement")
  • objectName :对象的名称(例如"Page")
  • actionName :操作的名称(例如"修改")
  • ID#1 执行操作的记录的ID,对象父级的ID
  • ID#2 :正在执行操作的记录的ID,但仅当ID#1填充了父ID时

导航是通过解析其组件的URL、将名称缩减为系统ID等进行的,然后检索要在页面上显示的字段和数据
为了确保URL保持可读性和逻辑可理解性,我不会在URL中添加多层父ID,而是将最后几层父ID保留在PHP $_SESSION数组中,这样我就可以在导航中确定是否必须添加不同的父ID。

示例:图像我们有对象Page->Extension->Field,它们都在模块PageManagement中,从左到右为父对象。现在假设我们有一个ID为2的Page、一个ID 8的Extension和一个ID 17的Field。编辑字段的URL将是example.com/PageManagement/Field/Modify/8/17,因为我们正在编辑字段17,它的扩展名为8。编辑扩展的URL将是example.com/PageManagement/Extension/Modify/2/8,因为我们正在编辑扩展8,它的父级是Page 2。编辑页面将只是example.com/PageManagement/Page/Modify/2,因为它没有父级。

问题:现在,所有这些都很完美但是,如果打开多个选项卡,它们共享相同的$_SESSION,因此在一个选项卡中导航可能会丢弃另一个选项卡的父历史记录。在几乎所有情况下,它仍然正确,但事实上我可能会导致它很糟糕(因为有人可能在不知道数据实际上在错误的父列表中的情况下添加/删除/编辑数据)。

我需要什么:对于每个请求,我需要一种方法来确定它来自哪个选项卡,很可能是通过为每个选项卡生成某种形式的UID并随每个请求一起发送。然后,我的系统可以按选项卡存储导航历史记录,而不是按会话存储。

考虑的解决方案

  • 为每个页面会话生成一个UID,并将其存储在Window.sessionStorage中(每个新窗口/选项卡都会重置)。这将允许我在还没有设置的情况下生成一个(因此是一个新的选项卡),从而在每个页面会话中存储(并记住)一个不同的选项卡。
    • 问题:我不知道如何在每次请求时将UID发送到服务器。会话cookie似乎在所有选项卡之间共享(这是有道理的,因为它们共享一个会话)
  • 为每个页面会话生成一个UID,并将其作为查询字符串附加到URL中。
    • 问题:我可能没有漂亮的URL,如果有人(意外)编辑/删除了它,它仍然无法工作。此外,复制/粘贴URL也是一个问题
  • 为每个页面会话生成一个UID,并在moduleName之前将其添加到URL中。
    • 问题:它仍然可见/可编辑/可移动,如果他们这样做,它仍然不起作用。此外,复制/粘贴URL也是一个问题

如果有人能解决上述解决方案中提到的问题,或者提出一个全新的解决方案,那将是令人惊叹的。显然,我更希望尽可能少地更改URL系统的工作方式,但如果这是唯一的解决方案,那就顺其自然吧…

您的请求设计中有一个基本缺陷,它给您带来了所有的麻烦
系统应尽可能将所有相关信息包含在单个请求中。在您的情况下,这意味着放弃$_SESSION中"记住"早期请求(状态..)的机制,而是传递请求中的所有信息。它可以在URL("地址"和/或查询字符串)、适当的标题(通常使用cookie。在这种情况下可能不合适)或正文(与POSTed表单传递有效载荷的方式相同)中。

选择这条道路的原因有很多,举几个例子:

  1. 改进日志记录
  2. 简化调试
  3. 启用简单的、基于URL的链接(仅使用请求的URL时)
  4. 降低错误缓存(本地或远程)的风险
  5. 支持多个"同时"请求->将有助于解决当前问题:-)

一如既往,没有一条规则是没有例外的。在这种情况下,最常见的不适合包含在每个请求中的信息是身份验证信息(用户名、密码等)

总之,您应该强烈考虑重新构建您的请求,以便获得所有必需的信息。