Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Session Laravel Package

customergauge/session

A Laravel package that captures and persists visitor session data such as landing pages, referrers, UTM parameters, and campaign attribution, making it easy to track how users arrive and move through your application across requests with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

This package bridges PHP's native $_SESSION superglobal into Laravel's authentication layer, so an app that already calls session_start() (legacy codebase, shared bootstrap, an old front controller) can still use Auth::user(), Auth::login(), and the auth middleware without rewriting session handling first. Treat it as an interop shim, not a general session driver.

Install and register

composer require customergauge/session

The service provider is auto-discovered on Laravel 5.5+. If you're on an older skeleton, add it to config/app.php manually. Publish any config the package ships:

php artisan vendor:publish --provider="CustomerGauge\Session\SessionServiceProvider"

Where to look first

  1. src/ — identify the two classes that matter: the session store/adapter (implements the Illuminate\Contracts\Session\Session surface or wraps $_SESSION) and the service provider that binds it. Read them before wiring anything; the package is small enough that the source is the documentation.
  2. composer.json — confirm the illuminate/* constraints match your Laravel version. With a single-digit star count and zero dependents, version compatibility is on you to verify.
  3. Your own public/index.php / bootstrap — decide where session_start() lives relative to bootstrap/app.php.

First use case: legacy login, Laravel auth

You have $_SESSION['user_id'] set by an old login script and want Laravel controllers to behave normally:

// config/auth.php
'guards' => [
    'web' => [
        'driver'   => 'session',
        'provider' => 'users',
    ],
],

Point the session driver at the native store (via the published config or a Auth::extend call in a service provider), make sure session_start() runs before the request is dispatched, then verify:

Route::get('/whoami', fn () => Auth::user()?->email ?? 'guest');

If that returns your legacy user, the bridge is working. If it returns null, dump $_SESSION and session_id() at the top of the route — the problem is almost always ordering or a second, competing session.

Implementation Patterns

Register a custom guard rather than swapping the global session driver. The safest integration is to leave Laravel's own session untouched (CSRF, flash messages, validation errors all depend on it) and only bridge authentication:

// app/Providers/AuthServiceProvider.php
Auth::extend('php-session', function ($app, $name, array $config) {
    return new SessionGuard(
        $name,
        $app['auth']->createUserProvider($config['provider']),
        $app['session.store'], // or the package's native adapter
    );
});

Then 'driver' => 'php-session' in config/auth.php. This keeps blast radius small.

Ordering is the whole game. In a legacy front controller:

session_start();                 // native session first
require __DIR__.'/vendor/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
$app->handleRequest(Request::capture());

If StartSession middleware or the package's bootstrapper runs first, you get two session stores fighting over state and intermittent "user randomly logged out" reports.

Dual-write during migration. While porting a legacy app, write identity to both stores on login and clear both on logout. This lets you migrate route groups at a time instead of a big-bang cutover:

public function login(Request $request)
{
    // legacy write
    $_SESSION['user_id'] = $user->id;

    // laravel write
    Auth::login($user);

    return redirect()->intended('/dashboard');
}

Keep the legacy logout contract. Native sessions are usually destroyed by session_destroy() plus setcookie(session_name(), '', time() - 3600). Hook your logout path so both worlds are cleaned:

public function logout()
{
    Auth::logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();

    $_SESSION = [];
    if (session_status() === PHP_SESSION_ACTIVE) {
        session_regenerate_id(true);
        session_destroy();
    }

    return redirect('/');
}

Middleware for hybrid route groups. Apply a small middleware to legacy-area routes that asserts a native session exists and 302s to the old login page — don't rely on Laravel's auth middleware, which will redirect to route('login') and confuse users mid-migration.

Testing. Native sessions are global process state; reset them in setUp():

protected function setUp(): void
{
    parent::setUp();
    $_SESSION = [];
    @session_start();
}

Then seed identity directly ($_SESSION['user_id'] = $user->id) instead of going through a login endpoint.

Gotchas and Tips

  • Two cookies, two sessions. Laravel's default cookie is laravel_session; PHP uses PHPSESSID. If both are active you'll see users authenticated in one request and anonymous in the next. Give them distinct cookie names and, ideally, distinct path/domain scopes while migrating.
  • Duplicate Cache-Control headers. Because both Laravel's StartSession middleware and PHP's native session module emit cache headers, you can end up with two Cache-Control values on the response — confusing proxies/CDNs and breaking strict header assertions in tests. Fixed in 2.3.0 (PR #12). If you're on 2.2.x or earlier, either upgrade or strip the duplicate in a small middleware ($response->headers->set('Cache-Control', ...)) before it reaches the client.
  • Never mix encryption expectations. Laravel encrypts and signs its session payload; native PHP sessions are plaintext server-side files. If you were relying on Laravel's session encryption at rest, you lose it. Check file permissions on session.save_path.
  • session_start() after output. Any whitespace before <?php in a legacy include produces "headers already sent" warnings and a silently broken session. Grep your includes for trailing newlines and BOMs.
  • Long-running workers are unsafe. Under Octane, Swoole, or RoadRunner, $_SESSION is process-global and leaks across requests. Do not use this package in that environment without an explicit per-request reset — and honestly, don't use it there at all.
  • CLI and queue contexts have no session. Auth::user() inside a job or Artisan command will be null or throw. Guard calls with app()->runningInConsole() or pass the user ID explicitly into jobs.
  • Native file sessions lock per-request. Concurrent AJAX requests from the same browser serialize on the session file. If you see slow dashboards after adopting this, that's why — call session_write_close() as early as safely possible, or switch session.save_handler to Redis.
  • Session fixation. On privilege change call session_regenerate_id(true) — the old ID must be destroyed, not just replaced. Verify with a browser devtools cookiejar that PHPSESSID actually rotates.
  • No remember-me parity. Laravel's remember_token cookie flow lives in SessionGuard; a thin native adapter may not implement viaRemember(). Test "stay logged in across browser restart" explicitly — it's the most common silent regression.
  • Debugging recipe: at the top of the failing route, log session_status(), session_id(), array_keys($_SESSION ?? []), Session::getId(), and Auth::id(). Nine times out of ten one column is empty and tells you exactly which layer dropped the state.
  • Pin the version. With 9 stars, 0 dependents, and a single maintainer, treat upgrades as potentially breaking — the 2.x line already carries a header-handling change you'll want, but verify it against your own response pipeline. Commit an exact constraint ("customergauge/session": "2.3.0") and keep a fallback: a 40-line Auth::extend closure that reads $_SESSION['user_id'] directly is a viable escape hatch if the package stalls.
  • Extension points worth knowing: the guard closure in Auth::extend and the session-store binding in the container are both swappable from your own service provider. If the package's adapter doesn't cover a case (e.g. getId() semantics, invalidate()), subclass it rather than patching vendor/.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib