Core

Session Service Provider

Session runtime, storage drivers and flash bag services.

Responsibility

Registers SessionStorageInterface, SessionInterface, NativeSession, alias session, FlashBagInterface, SessionFlashBag and alias flash. The provider selects storage from session.driver and exposes session/flash state to web controllers and request view helpers.

Session config

Application session config lives in app/Config/Session.php. Values are loaded under session.*; supported drivers are native, file, database and redis.

<?php

declare(strict_types=1);

use Lemonade\Framework\Support\Env;

return [
    'driver' => Env::string('SESSION_DRIVER', 'native'),
    'cookie' => Env::string('SESSION_COOKIE', 'LEMONADE_SESSION'),
    'lifetime' => Env::int('SESSION_LIFETIME', 7200),
    'native' => [
        'path' => Env::string('SESSION_NATIVE_PATH', 'writable/sessions'),
    ],
    'file' => [
        'path' => Env::string('SESSION_FILE_PATH', 'writable/sessions'),
    ],
    'database' => [
        'table' => Env::string('SESSION_DB_TABLE', 'sessions'),
    ],
    'redis' => [
        'host' => Env::string('SESSION_REDIS_HOST', '127.0.0.1'),
        'port' => Env::int('SESSION_REDIS_PORT', 6379),
        'database' => Env::int('SESSION_REDIS_DB', 0),
        'password' => Env::string('SESSION_REDIS_PASSWORD', ''),
        'prefix' => Env::string('SESSION_REDIS_PREFIX', 'sess:'),
        'timeout' => (float) Env::string('SESSION_REDIS_TIMEOUT', '2.5'),
    ],
];

Storage drivers

native uses PHP session runtime with a configured save path. file stores serialized payloads in framework-managed files. database uses ConnectionInterface and session.database.table. redis connects to configured Redis host/port/database/prefix. Unsupported driver names throw UnsupportedSessionDriverException.

Session service

SessionInterface exposes start(), started(), has(), get(), set(), remove(), clear() and regenerate(). NativeSession is the concrete session runtime and delegates to the configured storage.

use Lemonade\Framework\Session\Contract\SessionInterface;

final class FilterState
{
    public function __construct(
        private readonly SessionInterface $session,
    ) {}

    public function rememberCategory(string $category): void
    {
        $this->session->set('filter.category', $category);
    }

    public function category(): string
    {
        return (string) $this->session->get('filter.category', 'all');
    }
}

Flash bag

SessionFlashBag stores values in session key _flash. FlashBagInterface supports set(), get(), has(), remove(), pull(), all() and clear(); there are no typed helpers like success() or error() in the framework API.

use Lemonade\Framework\Session\Flash\FlashBagInterface;

final class ContactController
{
    public function __construct(
        private readonly FlashBagInterface $flash,
    ) {}

    public function submit(): ResponseInterface
    {
        $this->flash->set('contact.result', ['success' => true]);

        return $this->redirect('/contact');
    }
}

Flash lifecycle

Flash data is stored in session for the next request after a redirect. get() reads without removing; pull() returns the value and removes it immediately, which is the usual pattern for one-time messages or old form input.

$this->flash()->set('notice', 'Saved successfully.');

return $this->redirect('/contact');

// next request
$notice = $this->flash()->pull('notice');

Controller usage

Framework controllers expose flash() through AbstractController. Use the framework flash bag directly from controllers or inject FlashBagInterface into services that need request-to-request messages.

$this->flash()->set('notice', 'Saved successfully.');

if ($this->flash()->has('notice')) {
    $notice = $this->flash()->pull('notice');
}

View usage

ControllerServices creates RequestViewHelpers for views with optional session and flash services. Use $requestHelpers->flash() to pull one-time values in templates, or $requestHelpers->old() for old input stored under _old_input.* or flash key old_input.

<?php if (($notice = $requestHelpers->flash('notice')) !== null): ?>
    <div class="alert alert-success"><?= e($notice) ?></div>
<?php endif; ?>

<input name="email" value="<?= e($requestHelpers->old('email')) ?>">

Session lifecycle

Session storage starts lazily on first session operation. There is no dedicated session-start middleware in the current runtime; controllers, CSRF token manager, flash bag and request view helpers start session state by using the registered services.

Runtime scope

Sessions are for web/runtime state across requests, not persistent domain storage. Stateless API endpoints can avoid session/flash usage. Keep payloads small and store long-lived domain data in database/storage services instead.

Security relation

CSRF tokens are stored through SessionInterface, and flash messages use the same session runtime. The current session config documents cookie name, lifetime and driver-specific storage settings; secure/httpOnly/sameSite flags are not exposed in app/Config/Session.php.