pinga / session
Modern session management for PHP
Requires
- php: >=8.3.0
Suggests
- ext-redis: Use phpredis' native session handler for Redis-backed sessions
README
Modern session management for PHP with safer cookie defaults and support for PHP's native session storage handlers.
Pinga Session works with traditional file-based sessions, Redis through the phpredis extension, and other handlers supported by PHP. Application code does not change when switching storage backends.
Requirements
- PHP 8.3 or newer
- The PHP Redis extension when using Redis
Installation
Install the package using Composer:
composer require pinga/session
Usage
use Pinga\Session\Session; if (!Session::start()) { throw new RuntimeException('Unable to start the session'); } Session::set('user_id', 123); Session::set('username', 'example'); $userId = Session::get('user_id'); $username = Session::get('username', 'guest'); Session::close();
Call Session::close() after the last session change to write the data and release the session lock early.
Changes made to $_SESSION after Session::close() will not be persisted unless the session is started again.
Available methods
Session::start(); Session::id(); Session::regenerate(); Session::has('key'); Session::get('key', $defaultValue); Session::take('key', $defaultValue); Session::set('key', $value); Session::delete('key'); Session::close(); Session::isActive();
Session::take() returns a value and removes it from the session, making it useful for flash messages.
Regenerate the session ID after authentication or a privilege change:
if (!Session::regenerate()) { throw new RuntimeException('Unable to regenerate the session ID'); } Session::set('user_id', $userId);
SameSite cookies
The default SameSite policy is Lax.
Session::start(Session::SAME_SITE_RESTRICTION_LAX);
Available policies are:
Session::SAME_SITE_RESTRICTION_NONE; Session::SAME_SITE_RESTRICTION_LAX; Session::SAME_SITE_RESTRICTION_STRICT;
SameSite=None requires a secure HTTPS cookie:
Session::start( Session::SAME_SITE_RESTRICTION_NONE, ['cookie_secure' => true] );
SameSite cookies are an additional protection and do not replace CSRF tokens for state-changing requests.
Storage backends
Pinga Session does not choose the storage backend itself. PHP selects the backend through session.save_handler and session.save_path.
The same application code works with both file and Redis storage.
File sessions
File-based sessions require no additional PHP extension:
session.save_handler = files session.save_path = "/var/lib/php/sessions"
The session directory must exist, be writable by PHP, and not be publicly accessible.
Redis sessions
Install and enable the PHP Redis extension. On Debian or Ubuntu:
sudo apt install php-redis
Verify that it is enabled:
php -m | grep redis
When Redis runs on the same server, a Unix socket is recommended:
session.save_handler = redis session.save_path = "unix:///run/redis/redis-server.sock?prefix=pinga_session:&timeout=1&read_timeout=1"
Adjust the socket path to match your Redis installation.
Alternatively, use a TCP connection:
session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379?prefix=pinga_session:&timeout=1&read_timeout=1"
Recommended production settings
These settings apply to both file and Redis sessions:
session.auto_start = 0 session.use_strict_mode = 1 session.use_cookies = 1 session.use_only_cookies = 1 session.use_trans_sid = 0 session.gc_maxlifetime = 1800 session.cookie_lifetime = 0 session.cookie_path = / session.cookie_secure = 1 session.cookie_httponly = 1 session.cookie_samesite = Lax
session.cookie_secure requires HTTPS. Set it to 0 only in a local HTTP development environment.
When using Redis, also enable session locking:
redis.session.locking_enabled = 1 ; Must be longer than the application's normal maximum request time. redis.session.lock_expire = 60 ; Allow approximately two seconds to acquire a session lock. redis.session.lock_wait_time = 20000 redis.session.lock_retries = 100
For production, keep Redis on a private network or Unix socket. Use authentication, ACLs and TLS when connecting to a remote Redis server.
If Redis is unavailable, Session::start() can fail. Applications should handle this safely instead of silently falling back to file sessions.
Switching between files and Redis
To use file storage:
session.save_handler = files session.save_path = "/var/lib/php/sessions"
To use Redis through a Unix socket:
session.save_handler = redis session.save_path = "unix:///run/redis/redis-server.sock?prefix=pinga_session:&timeout=1&read_timeout=1"
Or through TCP:
session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379?prefix=pinga_session:&timeout=1&read_timeout=1"
After changing the configuration, restart PHP-FPM or the relevant web server.
Existing sessions are not migrated when switching storage backends. Users with sessions stored in the previous backend may need to sign in again.
No application code changes are required.
License
Pinga Session is licensed under the MIT License.