Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parent-Child navigation across multiple tabs

please bear with me for the explanation, it's necessary.

System background: I am creating a parent->child navigation system for the backend of a CMS. I build URLs like so: [domain.ext]/[moduleName]/[objectName]/[actionName]/[ID #1]/[ID #2].

The URL explained (e.g. example.com/PageManagement/Page/Modify/7/13):

  • moduleName: the name of the module the object belongs to (e.g. "PageManagement")
  • objectName: the name of the object (e.g. "Page")
  • actionName: the name of the action (e.g. "Modify")
  • ID #1: either the ID of the record the action is being performed on, or the ID of the object's parent
  • ID #2: the ID of the record the action is being performed on, but only if ID #1 is filled with a parent ID

Navigation happens by parsing the URL for its components, reducing the names to system IDs etc., and then retrieving the fields and data which are to be displayed on the page.
To ensure the URL remains readable and logically understandable I don't add multiple layers of parent ID's to the URL, but rather keep the last few parent IDs in the PHP $_SESSION array, so I can determine on navigation whether a different parent ID has to be added.

Example: image we have the objects Page->Extension->Field, which are all in the module PageManagement and parented from left to right. Now let's say we have a Page with ID 2, an Extension with ID 8, and a Field with ID 17. The URL for editing the Field would be example.com/PageManagement/Field/Modify/8/17, because we are editing Field 17, which has Extension 8 as parent. The URL for editing the Extension would be example.com/PageManagement/Extension/Modify/2/8, because we are editing Extension 8, which has Page 2 as parent. Editing the Page would simply be example.com/PageManagement/Page/Modify/2, because it has no parent.

Problem: Now, all of this works perfectly. However, if multiple tabs are opened they share the same $_SESSION, so navigating in one tab can throw off the parent history for the other tab. It still goes right in almost all cases, but the fact I can cause it is bad (since someone can be adding/deleting/editing data without knowing they are actually in the wrong parent list).

What I need: I need a way, with each request, to determine from which tab it came, most likely by generating some form of UID per tab and sending that with each request. My system can then store the navigation history per tab, instead of per session.

Considered solutions

  • Generating a UID per page session, and storing this in the Window.sessionStorage (which gets reset for each new window/tab). This would allow me to generate one if none is set yet (so a new tab), and thus have a different one stored (and remembered) per page session.
    • Problem: I don't know how I can get that UID sent to the server with each request. Session cookies seem to be shared between all tabs (makes sense since they share a session).
  • Generating a UID per page session, and appending that to the URL as a query string.
    • Problem: I might as well not have nice URLs, and if someone (accidentally) edits/removes it, it will still not work. Also, copy/pasting the URL will be a problem.
  • Generating a UID per page session, and prepending that to the URL before the moduleName.
    • Problem: It is still visible/editable/removable, and if they do it will still not work. Also, copy/pasting the URL will be a problem.

If anyone can solve the problems mentioned for the solutions above, or come up with a completely new solution, that would be amazing. Obviously I'd prefer make as few changes as possible to how the URL system works, but if that is the only solution, so be it...

like image 592
Byson Avatar asked Jun 30 '15 14:06

Byson


1 Answers

There's a basic flaw in your request design that's causing you all the trouble.
A system should strive to include all relevant information within a single request whenever possible. In your case, that means ditching the mechanism that "remembers" earlier requests (state..) in the $_SESSION and instead pass all the information in the request. It can be in the URL ("address" and/or query string), the headers when appropriate (Usually using cookies. Probably inappropriate in this case) or body (same way as POSTed forms pass the payload).

There are numerous reasons to choose this path, to name a few:

  1. Improve logging.
  2. Ease debugging.
  3. Enable simple, URL based linking (when using only the URL for requests).
  4. Reduce risk of incorrect caching (local or remote).
  5. Support multiple "simultaneous" requests -> Will help overcome current issue :-)

As always, no rule goes without exceptions. In this case, the most common piece of information that is NOT suitable to be included in each request is authentication information (username, password, etc...)

To summarize, you should strongly consider reconstructing your requests such that all required information is available.

like image 133
Amit Avatar answered Oct 04 '22 20:10

Amit