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 Bundle Laravel Package

theodo-evolution/session-bundle

Symfony bundle from Theodo Evolution that provides session management integration for Symfony apps, with services and configuration for handling user sessions through the framework. It offers a packaged session layer for projects that want session handling wired into Symfony rather than managed manu...

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate expectations: this is a Symfony2 bundle (PHP 5.3/5.4 era, Symfony 2.1–2.3), not a Laravel package. There is no service provider, no facade, no config/session.php integration. For a Laravel codebase you have two realistic paths:

  1. You maintain a legacy PHP ↔ Symfony2 hybrid — install it and let it swap Symfony's session storage for one backed by the legacy app's session. That is the package's entire reason for existing.
  2. You're Laravel-only — treat it as a ~200-line reference implementation for "how do I make two frameworks share one session?" and reimplement the idea against Laravel's SessionHandlerInterface / Store. This is the far more likely case; the repo has 46 stars and 0 dependents.

Where to look first (in this order)

  1. DependencyInjection/Configuration.php — the authoritative list of config keys. Don't trust README snippets; this file is the schema.
  2. Resources/config/services.yml (and any CompilerPass/) — this tells you how Symfony's session.storage is replaced. That wiring is the actual product.
  3. The class implementing Symfony's SessionStorageInterface — start(), getId(), getBag(), registerBag(), regenerate(), save(). This is the bridge.
  4. Tests/ — cheapest way to learn intended usage without standing up a legacy app.

Minimal Symfony2 install

composer require theodo-evolution/session-bundle
// app/AppKernel.php
public function registerBundles() {
    return [
        // ...
        new Theodo\Evolution\SessionBundle\TheodoEvolutionSessionBundle(),
    ];
}
# app/config/config.yml
framework:
    session:
        auto_start: false      # let the bridge control the lifecycle

theodo_evolution_session:
    storage: my_legacy_session_storage   # service id, see Configuration.php
    # exact key names vary by tag — confirm with:
    #   app/console config:dump-reference theodo_evolution_session

Point storage at a service that wraps your legacy session (a $_SESSION-backed adapter, or your legacy SessionHandlerInterface). After that, $request->getSession()->get('user') and $_SESSION['user'] read the same data.

First use case

The canonical one: the legacy app authenticates and writes $_SESSION['user_id']; a Symfony2 controller needs to read that identity and act on it. Get this working read-only before you allow writes from the Symfony side — reads are safe, writes are where you corrupt sessions.

Laravel analogue to build: a LegacySessionStore extends Illuminate\Session\Store whose read() proxies to the legacy handler, registered via a custom SessionHandlerInterface in config/session.php, plus a StartSession-replacement middleware that boots the legacy session before Laravel's.

Implementation Patterns

1. Storage swap, not call-site swap

The bundle's core move is replacing the container's session.storage service so every Symfony consumer — security, flash bag, CSRF — is unaware of the bridge. Copy that discipline in Laravel: swap the session handler, never sprinkle $_SESSION reads through controllers. If your controllers know about the bridge, you can't remove it later.

2. Namespaced attribute bags over a flat legacy array

Legacy $_SESSION is a flat hash; Symfony uses namespaced bags (_symfony_flashes, _security_<firewall>). The workable pattern is: legacy keys live at the root, Symfony bag contents live under one reserved key (e.g. $_SESSION['_bridge'] = ['flashes' => [...], 'security' => [...]]). Never let Symfony's default bag write to root — it will stomp legacy keys.

In Laravel the equivalents are _flash.new / _flash.old / _token / login_web_<hash>. Put them under a single reserved prefix.

3. Two handoff orders, and you must pick one

  • Legacy-first: index.php (legacy) boots, starts the session, then includes the Symfony front controller. Symfony must not call session_start() again — configure auto_start: false and have the bridge adopt the already-open session.
  • Symfony-first: Symfony boots and lazily opens the session; the legacy code is reached via a controller that includes it. Here you must ensure the legacy bootstrap doesn't session_start() a second handler.

Pick one per route/URL prefix and be consistent. Mixing them per-request is the #1 source of "my session data vanished" bugs.

4. Cookie and handler alignment (works for Symfony and Laravel alike)

Two separate PHP processes only share a session if all of these match:

Setting Must match
session.name cookie name
cookie path / domain / secure exactly
session.save_handler files only works on one host; use Redis/DB/memcached for multi-host
session.save_path shared volume or shared server
session.gc_maxlifetime otherwise one app reaps the other's sessions

If you're on multiple app servers, step one is moving both sides to a shared Redis handler — the bridge won't save you from divergent save_paths.

5. Coordinated lifecycle, single writer

A good pattern is to make the bridge read-through/write-through but only flush once, at kernel.terminate (Symfony) or TerminateMiddleware (Laravel). That gives you one save point, one regenerate() point, and one place to log diffs. Avoid session_write_close() in the legacy bootstrap before the Symfony side has read — subsequent reads return stale/empty data.

6. Dual-write while migrating

During transition, wrap the storage in a decorator that reads from the legacy store and writes to both the legacy store and a clean Symfony/Laravel store. Once traffic is flipped and the legacy store is cold, drop the decorator. This decorator is also your observability layer — log every key read/written and you'll find the collisions in an afternoon.

7. Test against an array, not a superglobal

$_SESSION in unit tests is a global you'll forget to reset. Fake the underlying handler with an in-memory array and test the storage implementation directly: start → get → set → save → new instance → get. This is the only part of the bundle genuinely worth porting verbatim.

Gotchas and Tips

It will not install on a modern stack. Symfony 2.x constraints + PHP 5.x syntax means composer require fails on PHP 8 / Symfony 5+. Vendor the source (it's small) or fork and patch. Do not expect upstream fixes: 46 stars, 0 dependents, no security response.

$_SESSION is a superglobal; copying breaks it. If your storage does $this->data = $_SESSION on start and $_SESSION = $this->data on save, any legacy code holding a reference — or writing between those points — silently diverges. Either hold a reference or make the save unconditional and last.

Bag registration ordering. Symfony throws if you getFlashBag() / getBag() before the bag is registered, and a swapped storage must still register the default bags. If you see The SessionBag ... is not registered, the bridge is starting the session without delegating bag registration. Register bags before start().

Logout and session_destroy() are shared. The legacy app's logout destroys the whole session — including Symfony's security token and flash queue. That's usually desirable, but it means Symfony's logout handler and the legacy logout must not both run, or you'll regenerate an ID twice and log the user out of the wrong context. Centralize logout in one place.

Flash bags are pop-on-read. Symfony's flash bag empties on getFlashBag()->get(). If the legacy side also reads that key, one side sees the message and the other doesn't. Treat flashes as owned by exactly one app; the bridge should not try to be clever here.

Session fixation / trust boundary. Never let a legacy app write an identity key that Symfony's security.context then trusts without re-validation. A legacy session id is not proof of authentication once two apps share the cookie. Re-check the user against your user provider after the bridge reads it.

Config quirks to check explicitly:

  • framework.session.auto_start: false — non-negotiable in legacy-first mode.
  • Whether the bundle replaces session.storage or merely aliases it; run app/console debug:container session.storage and read the class name it resolves to. If it's still NativeSessionStorage, your config key was silently ignored (config:dump-reference first).
  • framework.session.storage_id may need to point at the bridge service, depending on version.

Debugging recipe:

  1. var_dump(session_id(), session_name()) at the top of both entry points — they must match before anything else runs.
  2. var_dump($_SESSION) immediately after both bootstraps — diff the two arrays.
  3. Wrap the storage in a logging decorator (see pattern 6); 90% of bridge bugs are a write that happened after the save.
  4. Run both apps on the same host and same save_path first. Only then move to shared storage — otherwise you're debugging two problems.

Extension points worth knowing: a custom AttributeBag if you need to name-map legacy keys without touching either app; a kernel.request listener at high priority if the session must be live before Symfony's own listener; a kernel.terminate listener for the single write-back. These three hooks reimplement cleanly in Laravel as a bootstrap() in app.php, a prepended global middleware, and a terminating middleware respectively.

Bottom line: don't add this to composer.json — read it. The storage decorator, the bag namespacing decision, and the single-write-point pattern are the transferable ideas, and they're 200 lines you can port into a Laravel Store subclass in a day. The Symfony2 wiring itself is dead weight.

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