Lightweight session management library for PHP - object-oriented.
composer require codemonster-ru/sessionuse Codemonster\Session\Session;
// Start session (default: file storage)
Session::start();
// Store values
Session::put('user', 'Vasya');
Session::put('role', 'admin');
// Retrieve values
echo Session::get('user'); // Vasya
// Remove values
Session::forget('role');
// Get all session data
print_r(Session::all());
// Destroy current session
Session::destroy();// Rotate ID after login or privilege change
Session::regenerate();// Force new ID at start (keeps data, destroys old session)
Session::start(options: ['regenerate' => true]);Session::start(options: [
'cookie' => [
'secure' => true,
'samesite' => 'Strict',
'lifetime' => 3600,
'path' => '/',
'domain' => 'example.com'
]
]);Notes:
- If
secureis not provided, it is set automatically when HTTPS is detected. - If
samesiteisNone,secureis forced totrue.
Session::start(options: [
'cookie' => [
'secure' => true,
'httponly' => true,
'samesite' => 'Strict',
'lifetime' => 60 * 60 * 24,
'path' => '/'
]
]);use Codemonster\Session\Session;
$key = random_bytes(32);
Session::start(options: [
'encryption' => [
'key' => $key,
// Optional: allow decrypting existing plaintext sessions
// Also triggers auto-migration to encrypted payload on first read
'allow_plaintext' => true,
// Optional: previous keys for rotation
'previous_keys' => []
]
]);$oldKey = random_bytes(32);
$newKey = random_bytes(32);
Session::start(options: [
'encryption' => [
'key' => $oldKey,
'allow_plaintext' => true
]
]);
// rotate to a new key, keeping the old key for decryption
Session::rotateEncryptionKey($newKey, [$oldKey]);// Store keys in env/secret manager; use base64 for readability.
$currentKey = base64_decode(getenv('SESSION_KEY'), true);
$previousKey = base64_decode(getenv('SESSION_KEY_PREV'), true);
Session::start(options: [
'encryption' => [
'key' => $currentKey,
'previous_keys' => array_filter([$previousKey]),
'allow_plaintext' => false
]
]);- Deploy with
previous_keyscontaining the old key andkeyas the new key. - Keep
allow_plaintext=falseif you already migrated to encryption. - After rotation window, remove the old key from
previous_keys.
Session::start('array');
Session::put('debug', true);
echo Session::get('debug'); // trueSession::put('count', 1);
Session::increment('count', 2); // 3
Session::put('token', 'abc');
Session::has('token'); // true
Session::pull('token'); // 'abc'
Session::has('token'); // false
Session::put('a', 1);
Session::put('b', 2);
Session::forgetMany(['a', 'b']);
// Flash data lasts for the next start and is then removed
Session::flash('notice', 'Saved');Session::putWithTtl('token', 'abc', 60); // expires in 60 seconds
Session::sweepExpired(); // optional manual cleanup
Session::ttl('token'); // remaining seconds
Session::expiresAt('token'); // unix timestamp
Session::touch('token', 120); // extend TTL$admin = Session::for('admin');
$user = Session::for('user');
$admin->put('token', 'admin123');
$user->put('token', 'user456');$admin = Session::for('admin');
$admin->keys(); // ['token', ...]
$admin->forgetNamespace();
Session::count(); // count of user keys
Session::touchAll(120); // extend TTL for all keys
Session::touchAll(120, 'admin.'); // extend only for namespace
Session::keys(); // ['admin.token', 'user.token', ...]
Session::forgetNamespace('user');$scope = Session::for('admin', ':');
$scope->put('token', 'x'); // stored as admin:tokenSession::dump(); // array of user-visible keys/values
Session::dump(['token']); // redact selected keys
Session::dump([], ['user*']); // redact by pattern
Session::size(); // payload size in bytesSession::keys(); // all keys
Session::keysMatch('user*'); // wildcard match$manager = Session::manager();
$manager->put('token', 'abc');
$scoped = $manager->for('admin');
$scoped->put('token', 'admin123');use Codemonster\Session\Session;
use App\Session\RedisSessionHandler;
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$handler = new RedisSessionHandler($redis);
Session::start(customHandler: $handler);
Session::put('user_id', 42);use Codemonster\Session\Handlers\RedisSessionHandler;
use Codemonster\Session\Session;
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$handler = new RedisSessionHandler($redis, prefix: 'sess_', ttl: 3600, retries: 2, retryDelayMs: 100);
Session::start(customHandler: $handler);use Codemonster\Session\Handlers\RedisClusterSessionHandler;
use Codemonster\Session\Session;
$cluster = new RedisCluster(null, ['127.0.0.1:7000', '127.0.0.1:7001']);
$handler = new RedisClusterSessionHandler($cluster, prefix: 'sess_', ttl: 3600, retries: 2, retryDelayMs: 100);
Session::start(customHandler: $handler);use Codemonster\Session\Handlers\RedisSentinelSessionHandler;
use Codemonster\Session\Session;
$sentinel = new RedisSentinel('127.0.0.1', 26379);
$handler = new RedisSentinelSessionHandler(
$sentinel,
service: 'mymaster',
prefix: 'sess_',
ttl: 3600,
retries: 2,
retryDelayMs: 100
);
Session::start(customHandler: $handler);use Codemonster\Session\Handlers\PredisSessionHandler;
use Codemonster\Session\Session;
use Predis\Client;
$client = new Client('tcp://127.0.0.1:6379');
$handler = new PredisSessionHandler($client, prefix: 'sess_', ttl: 3600, retries: 2, retryDelayMs: 100);
Session::start(customHandler: $handler);use Codemonster\Session\Handlers\CacheSessionHandler;
use Codemonster\Session\Session;
use Psr\SimpleCache\CacheInterface;
/** @var CacheInterface $cache */
$handler = new CacheSessionHandler($cache, prefix: 'sess_', ttl: 3600, retries: 2, retryDelayMs: 100);
Session::start(customHandler: $handler);You can run tests with the command:
composer testStatic analysis:
composer analyse
composer psalmRedis integration tests (optional):
REDIS_TESTS=1 composer testRedis Sentinel/Cluster integration tests (optional):
REDIS_SENTINEL_TESTS=1 composer test
REDIS_CLUSTER_TESTS=1 composer testStress test (optional):
composer stress
composer stress -- 20000 array
composer stress -- 20000 file
REDIS_HOST=127.0.0.1 REDIS_PORT=6379 composer stress -- 20000 redis
# With thresholds: iterations, driver, min_ops, max_seconds
composer stress -- 20000 array 3400 6
composer stress -- 10000 file 1700 6
composer stress -- 20000 redis 400 6Note: thresholds depend on runner performance; recalibrate if CI hardware changes.
Security reports: email admin@codemonster.net with a clear description and steps to reproduce.
Security checklist:
- Use HTTPS and
securecookies in production. - Set
SameSitetoStrictorLaxbased on your flow. - Use
httponlyto reduce XSS access to cookies. - Rotate session IDs after login or privilege changes.
- Consider payload encryption (
encryption.key) for sensitive data. - Keep session storage private and with proper file permissions.