Download the PHP package seba1rx/tabmanager without Composer

On this page you can find all versions of the php package seba1rx/tabmanager. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package tabmanager

TabManager

Package name: seba1rx/tabmanager

TabManager provides per-tab session isolation for PHP applications. It ensures each browser tab maintains its own independent session state, preventing shared session data between tabs — useful for admin dashboards, multi-step forms, or any multi-tab workflow.


How It Works

Each browser tab receives a unique UUIDv4 generated by the JS client and stored in sessionStorage. On every AJAX request the UUID is sent as the X-TabManager-TabId header. The PHP backend reads this header to isolate $_SESSION data under that UUID.

Why a header instead of a cookie? Cookies are shared across all tabs for the same domain — if Tab B sets a new tab-ID cookie, Tab A's cookie is overwritten immediately. The header is sent per-request with the correct UUID from sessionStorage, which is strictly per-tab.

Duplicate-tab detection: when a browser duplicates a tab it copies sessionStorage, so the new tab would inherit the original's UUID. On init the JS client uses the BroadcastChannel API to ask whether any other running tab already claims that UUID. If yes, a fresh UUID is generated before the tab registers with the server.

Heartbeat: while a tab is visible the JS client POSTs to the heartbeat endpoint every 30 s, keeping last_active accurate on the server. The heartbeat pauses when the browser hides or freezes the tab (Page Visibility API) and resumes — with an immediate beat — when the tab becomes visible again.


AI-assisted implementation

The package ships with llms.txt — a structured reference document written for AI coding assistants. It covers the full integration flow, every method and configuration option, security constraints, common mistakes, and a minimal working example.

If you are implementing this package with the help of an AI assistant (Claude, Copilot, Cursor, etc.), point it at that file before asking it to write integration code:


Implementation Guide

Step 1 — Install

The Composer post-install script copies seba1rx_tabmanagerclient.js to your project root automatically.


Step 2 — Include the JS client in your HTML

Add the script tag before your own application scripts. Optionally set configuration globals in an inline script before it.

The client runs automatically on DOMContentLoaded. It assigns a UUID to the tab, detects duplicates, sets a fallback cookie, notifies the backend, and starts the heartbeat.


Step 3 — Await TabManagerClient.ready before using the tab ID

init() is async (it waits ~80 ms for the BroadcastChannel duplicate check). If your scripts read TabManagerClient.tab.id or call getHeaders() before init completes they will get null.


Step 4 — Add the tab header to every AJAX call

Spread TabManagerClient.getHeaders() into the headers object of every fetch or XMLHttpRequest that talks to your PHP backend. This sends X-TabManager-TabId: <uuid> so the server knows which tab is making the request.

Calls that omit getHeaders() will fall back to the TABMANAGER_TABID cookie, which is shared across tabs and therefore unreliable for tab isolation.


Step 5 — Use TabManager in your PHP endpoints

The bootstrap file runs automatically on every require 'vendor/autoload.php', registering the internal endpoints. You do not need to include or configure anything extra.

In any PHP file that handles a request from the JS client:

TabManager::set() and get() resolve the tab UUID from the X-TabManager-TabId header automatically — you never handle the UUID manually.


Step 6 — (Optional) Expose a heartbeat endpoint

The JS client POSTs to /tabmanager/heartbeat by default. This endpoint is registered automatically by the bootstrap in any setup where all requests are routed through a PHP front controller (the standard setup for frameworks and SPAs with a catch-all route).

If your setup does not route /tabmanager/* to PHP (e.g. php -S without a router, or a framework that only routes registered paths), create a dedicated PHP file and point the client at it:


HTTP Endpoints

Registered automatically on every require 'vendor/autoload.php':

Method Endpoint Description
POST /tabmanager/new-tab Register a new tab in session
POST /tabmanager/heartbeat Update last_active for a tab
POST /tabmanager/tab-close Mark a tab as inactive
GET /tabmanager/tab-status Returns { "indexed": bool } — whether the tab still exists in session
GET /tabmanager/debug_js Session dump as JSON (debug only)
GET /tabmanager/debug_html Session dump as HTML table (debug only)
POST /tabmanager/debug/delete-tab Delete a tab session (debug only)

These endpoints intercept the request before your application router runs and call exit. They are invisible to your framework.

Debug endpoints are only accessible when define('TABMANAGER_DEBUG', true) is set. There is no IP-based fallback — REMOTE_ADDR checks were removed because reverse proxies always report 127.0.0.1 as the client IP.


PHP Class Reference

Method Description
indexNewTab(string $tabId) Registers a new tab in session (idempotent)
touchTab(string $tabId) Updates last_active and is_active; creates the tab if missing
set(string $key, mixed $value) Stores a value in the current tab's session slot
get(string $key, mixed $default = null) Retrieves a value from the current tab's session slot
destroyTabSession(string $tabId) Deletes all session data for a tab
markInactiveTab(string $tabId) Sets is_active = false (called on beforeunload)
isTabIndexed(?string $tabId = null): bool Returns whether a tab is registered; resolves current tab from header/cookie when no argument given
cleanupInactiveTabs(int $olderThanSeconds): int Removes inactive tabs older than the given threshold; returns count deleted
getTabIdStrict(): ?string Reads X-TabManager-TabId header only — no cookie fallback. Use for sensitive endpoints.
debug(): array Returns a summary of all tab sessions
uuid_v4(): string Generates a UUIDv4 (utility for consumers)
is_valid_uuid(string $uuid, bool $onlyV4) Validates UUID format (utility for consumers)

Custom session store

By default TabManager manages the session itself using native PHP functions (session_start(), $_SESSION). If your application already handles the session — for example, through a session-management package — you can delegate session responsibility to a custom class and pass it to the constructor.

The contract

Seba1rx\TabManager\Contracts\SessionStoreInterface defines six methods:

Using the default store (standard setup)

When no store is provided, TabManager instantiates PhpSessionStore internally:

Injecting a custom store

Implement the interface and pass your store to the constructor:

TabManager calls $store->start() in the constructor. If the session is already active your start() implementation can be a no-op. All set(), get(), has(), and remove() calls use the store root — TabManager manages its own 'tabmanager' key internally.


JS Client Reference

Member Description
TabManagerClient.ready Promise that resolves when init() completes. Always await before using tab.id.
TabManagerClient.tab.id The confirmed UUID for this tab. null until ready resolves.
TabManagerClient.getHeaders() Returns { 'X-TabManager-TabId': <uuid> }. Spread into every AJAX call.
TabManagerClient.heartbeat.send() Sends one heartbeat manually.
TabManagerClient.heartbeat.start() Starts the heartbeat interval.
TabManagerClient.heartbeat.stop() Stops the heartbeat interval.

JS Configuration

Set these globals before loading the script:

Variable Default Description
window.TABMANAGER_DEBUG false Enables verbose console logging
window.TABMANAGER_HEARTBEAT_URL /tabmanager/heartbeat Heartbeat endpoint URL
window.TABMANAGER_HEARTBEAT_INTERVAL 30000 Heartbeat interval in milliseconds
window.TABMANAGER_NEW_TAB_URL /tabmanager/new-tab Override new-tab registration endpoint
window.TABMANAGER_TAB_CLOSE_URL /tabmanager/tab-close Override tab-close notification endpoint
window.TABMANAGER_TAB_STATUS_URL /tabmanager/tab-status Override tab-status check endpoint

Detecting session loss after tab suspension

When a browser suspends a tab (e.g. Chrome Memory Saver) the JS heartbeat stops. If your app calls cleanupInactiveTabs() in the meantime, the tab's session slot may be deleted. When the user returns to the tab, TabManager detects this automatically and dispatches a tabmanager:session-lost event on document.

Listen for it to show a warning — the UI is entirely up to your app:

The check runs silently on every visibilitychange to visible. If the endpoint is unreachable (network error, 404) the event is not fired — the client fails open to avoid false positives.

For php -S setups without a router, point the client at a physical file:


Session Data Structure


Debug Interface

Enable debug mode in PHP:

Then visit /tabmanager/debug_html for a table showing all tabs, their status, last active time, stored keys, and a delete button per tab.

Enable JS logging:


Security notes


Unit tests

The package includes a PHPUnit test suite covering all public methods of TabManager.

What is tested:

Class / method Scenarios covered
isValidTabId() Valid UUID v4 (lower/upper/mixed case), wrong version digit, wrong variant nibble, empty string, arbitrary string, too short, too long, invalid hex chars, missing hyphens
__construct() Session structure initialization, existing data not overwritten, other session keys untouched, default store (PhpSessionStore), custom store injection
indexNewTab() data initialized as empty array, is_active defaults to true, last_active set to current time, idempotency
touchTab() last_active updated, inactive tab reactivated, data not modified, creates tab if not registered
set() Value stored correctly, last_active updated, tab reactivated, no-op when tab not registered (SEC-04), no-op when no tab ID present, key overwrite, cookie fallback, various value types
get() Returns stored value, returns null for absent key, returns custom default, returns default when tab not registered, returns default when no tab ID
markInactiveTab() Sets is_active = false, data and last_active preserved, no-op for unregistered tab
destroyTabSession() Removes tab entry, sibling tabs unaffected, no-op for unregistered tab
isTabIndexed() Returns true for registered tab, false for unregistered, explicit UUID argument, resolves current tab from header, returns false when no ID present
cleanupInactiveTabs() Removes stale inactive tab, preserves active tab, preserves recent inactive tab, returns 0 when nothing to clean, no-op for threshold ≤ 0
debug() Empty array when no tabs, correct structure (is_active, last_active, keys, size), last_active formatted as Y-m-d H:i:s, keys contains data key names, size matches json_encode byte length
getTabIdStrict() Returns header value, returns null when only cookie present, returns null when nothing present

Tests use an in-memory ArraySessionStore (implements SessionStoreInterface) — no PHP session functions, no files written, fully isolated.


Integration with seba1rx/sessionadmin

If your application uses seba1rx/sessionadmin for session management, use SessionAdminBridge instead of TabManager directly. The bridge implements TabHandlerInterface (defined in sessionadmin) and lets SessionAdmin own the session lifecycle, so both packages share the same PHP session without conflict.

SessionAdminBridge does not call session_start() in its constructor — SessionAdmin starts the session with the correct name and cookie parameters. Once the session is active, all tab methods work normally.

Bootstrap endpoints and custom session names: When SessionAdmin configures a custom session name (e.g. $this->sessionName = 'my_app'), the tabmanager bootstrap endpoints (/tabmanager/new-tab, /tabmanager/heartbeat, etc.) must use the same session name. Set session_name() before require 'vendor/autoload.php' in the entry point that handles those requests, or route them through a script that calls $session->activateSession() first.


Requirements


License

MIT License © 2025 Seba1rx


All versions of tabmanager with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package seba1rx/tabmanager contains the following files

Loading the files please wait ...