PHPackages                             baraja-core/session - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. baraja-core/session

ActiveLibrary[Database &amp; ORM](/categories/database)

baraja-core/session
===================

Simple performance package for storage your sessions to database by native PDO.

v1.4.0(4y ago)12.4k[4 issues](https://github.com/baraja-core/session/issues)PHPPHP ^8.1CI failing

Since Dec 3Pushed 4mo ago1 watchersCompare

[ Source](https://github.com/baraja-core/session)[ Packagist](https://packagist.org/packages/baraja-core/session)[ Docs](https://github.com/baraja-core/session)[ RSS](/packages/baraja-core-session/feed)WikiDiscussions master Synced 4d ago

READMEChangelog (10)Dependencies (11)Versions (15)Used By (0)

PHP Native PDO Session Storage
==============================

[](#php-native-pdo-session-storage)

Simple, high-performance package for storing PHP sessions in a MySQL database using native `\PDO`. This package provides a robust database-backed session handler that works seamlessly with both native PHP applications and the Nette Framework.

🎯 Key Features
--------------

[](#-key-features)

- **Native PDO Implementation** - Uses PHP's native PDO extension for reliable database connections with prepared statements
- **Framework Agnostic** - Works with native PHP applications out of the box
- **Nette Framework Integration** - Includes DI extension for seamless Nette integration
- **Doctrine ORM Support** - Optional entity mapping for Doctrine-based applications
- **Automatic Garbage Collection** - Probabilistic GC with configurable session lifetime (14 days default)
- **CLI Safe** - Automatically skips session operations in CLI mode to prevent errors
- **Binary Data Support** - Automatic Base64 encoding fallback for problematic session data
- **Tracy Debugger Integration** - Logs errors to Tracy when available
- **Custom Table Names** - Configurable database table name for multi-tenant applications

🏗️ Architecture Overview
------------------------

[](#️-architecture-overview)

The package consists of three main components that work together to provide database session storage:

```
┌─────────────────────────────────────────────────────────────────┐
│                     Application Layer                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Native PHP                          Nette Framework           │
│   ───────────                         ───────────────           │
│   session_set_save_handler()          SessionExtension          │
│           │                                  │                  │
│           │                                  │                  │
│           ▼                                  ▼                  │
│   ┌───────────────────────────────────────────────────┐        │
│   │              SessionStorage                        │        │
│   │         implements \SessionHandlerInterface        │        │
│   │                                                    │        │
│   │  • open()    - Initialize connection               │        │
│   │  • close()   - Cleanup                             │        │
│   │  • read()    - Load session data                   │        │
│   │  • write()   - Persist session data                │        │
│   │  • destroy() - Remove session                      │        │
│   │  • gc()      - Garbage collection                  │        │
│   └───────────────────────────────────────────────────┘        │
│                           │                                     │
│                           │ PDO                                 │
│                           ▼                                     │
│   ┌───────────────────────────────────────────────────┐        │
│   │              MySQL Database                        │        │
│   │         core__session_storage table                │        │
│   │                                                    │        │
│   │  • id (varchar 26) - Session identifier            │        │
│   │  • haystack (longtext) - Serialized data           │        │
│   │  • last_update (datetime) - Last modification      │        │
│   └───────────────────────────────────────────────────┘        │
│                                                                 │
│   Optional: SessionEntity (Doctrine ORM mapping)                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

```

🧩 Components
------------

[](#-components)

### SessionStorage

[](#sessionstorage)

The core component implementing PHP's `\SessionHandlerInterface`. It handles all session operations:

- **Connection Management**: Creates a dedicated PDO connection with proper character encoding (UTF-8) and error handling
- **Session Reading**: Retrieves session data from database, handles Base64-encoded data transparently
- **Session Writing**: Persists session data with automatic timestamp updates, falls back to Base64 encoding for binary data
- **Session Destruction**: Removes session records from the database
- **Garbage Collection**: Probabilistic cleanup (0.1% chance per request) removing sessions older than 14 days, limited to 500 records per run

### SessionExtension

[](#sessionextension)

A Nette Framework DI extension that provides:

- **Automatic Service Registration**: Registers `SessionStorage` as a service
- **Doctrine Integration**: Automatically registers entity paths when Doctrine is present
- **DBAL Connection Reuse**: Can inherit database credentials from existing Doctrine DBAL connection
- **Session Handler Setup**: Automatically configures Nette's Session to use the database handler

### SessionEntity

[](#sessionentity)

A Doctrine ORM entity class providing:

- **Entity Mapping**: Proper ORM annotations for the session table
- **Type Safety**: Strongly typed properties for session data
- **Immutable Timestamps**: Uses `DateTimeImmutable` for the last update field

📦 Installation
--------------

[](#-installation)

It's best to use [Composer](https://getcomposer.org) for installation, and you can also find the package on [Packagist](https://packagist.org/packages/baraja-core/session) and [GitHub](https://github.com/baraja-core/session).

To install, simply use the command:

```
$ composer require baraja-core/session
```

You can use the package manually by creating an instance of the internal classes, or register a DIC extension to link the services directly to the Nette Framework.

### Requirements

[](#requirements)

- PHP 8.1 or higher
- PDO extension (`ext-PDO`)
- MySQL database

🗄️ Database Setup
-----------------

[](#️-database-setup)

Create the database table `core__session_storage` (table name can be configured) or use Doctrine for automatic schema generation.

### MySQL Table Schema

[](#mysql-table-schema)

```
SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';

CREATE TABLE `core__session_storage` (
  `id` varchar(26) COLLATE utf8_unicode_ci NOT NULL,
  `haystack` longtext COLLATE utf8_unicode_ci NOT NULL,
  `last_update` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
```

> **Note**: The table can be used with Doctrine ORM or as a standalone MySQL table.

### Using Doctrine Migrations

[](#using-doctrine-migrations)

If you're using Doctrine ORM, the schema can be generated automatically from the `SessionEntity` class. Simply run your standard Doctrine migration commands:

```
$ php bin/console doctrine:schema:update --force
```

⚙️ Configuration
----------------

[](#️-configuration)

### Native PHP Usage

[](#native-php-usage)

For standalone PHP applications, create a `SessionStorage` instance and register it as the session handler:

```
$handler = new \Baraja\Session\SessionStorage(
   '127.0.0.1',      // MySQL host
   'my_application', // Database name
   'root',           // Username
   '****'            // Password
);

session_set_save_handler($handler);
session_start();
```

> **Warning**: The session handler must be registered **before** calling `session_start()`!

### Nette Framework Usage

[](#nette-framework-usage)

Register the extension in your NEON configuration file:

```
extensions:
   barajaPdoSession: Baraja\Session\SessionExtension
```

The session storage will be configured automatically.

#### Manual Configuration

[](#manual-configuration)

If you need to specify database credentials explicitly:

```
extensions:
   barajaPdoSession: Baraja\Session\SessionExtension

barajaPdoSession:
   host: 127.0.0.1
   dbName: my_application
   username: root
   password: ****
   table: core__session_storage  # optional, this is the default
```

#### Automatic Doctrine DBAL Integration

[](#automatic-doctrine-dbal-integration)

When using the `baraja-core/doctrine` package, the extension automatically inherits database credentials from your existing DBAL connection. No additional configuration is required!

🔧 Advanced Configuration
------------------------

[](#-advanced-configuration)

### Custom Table Name

[](#custom-table-name)

You can customize the database table name in two ways:

**1. Via Constructor Parameter:**

```
$handler = new \Baraja\Session\SessionStorage(
   'localhost',
   'mydb',
   'user',
   'password',
   'my_custom_sessions_table'  // Custom table name
);
```

**2. Via Setter Method:**

```
$handler = new \Baraja\Session\SessionStorage(/* ... */);
$handler->setTable('my_custom_sessions_table');
```

**3. Via NEON Configuration (Nette):**

```
barajaPdoSession:
   table: my_custom_sessions_table
```

> **Note**: The default table name is `core__session_storage`. While the table name can be changed at runtime, it is not recommended.

### Garbage Collection

[](#garbage-collection)

The garbage collector runs automatically with a 0.1% probability on each request. It:

- Removes sessions that haven't been updated in 14 days
- Processes a maximum of 500 records per run to prevent long-running queries
- Is skipped entirely in CLI mode

🔒 Security Considerations
-------------------------

[](#-security-considerations)

### Session Data Encoding

[](#session-data-encoding)

When session data contains characters incompatible with MySQL's UTF-8 encoding, the package automatically:

1. Detects the encoding failure via PDO exception
2. Re-encodes the data using Base64 with a `_BASE:` prefix
3. Transparently decodes on read

This ensures binary data and special characters are safely stored without data loss.

### CLI Mode Protection

[](#cli-mode-protection)

Session operations are automatically skipped in CLI mode (detected by absence of `$_SERVER['REMOTE_ADDR']`). This prevents:

- Errors when running console commands
- Unnecessary database connections in CLI scripts
- Accidental session manipulation from cron jobs

### Error Handling

[](#error-handling)

- Database query failures throw `\RuntimeException` with helpful error messages
- Session corruption errors are logged to Tracy (if available) and display a user-friendly error message
- Failed session writes gracefully degrade without crashing the application

🔍 How It Works
--------------

[](#-how-it-works)

### Session Lifecycle

[](#session-lifecycle)

1. **Initialization**: When a request arrives, `SessionStorage` creates a PDO connection
2. **Reading**: The `read()` method fetches session data by ID, creating a new record if none exists
3. **Processing**: Your application uses `$_SESSION` as normal
4. **Writing**: At request end, `write()` updates the session record with new data and timestamp
5. **Cleanup**: GC randomly triggers to remove old sessions (0.1% probability)

### Data Flow

[](#data-flow)

```
┌─────────────┐     ┌──────────────────┐     ┌──────────────┐
│   Request   │────▶│  SessionStorage  │────▶│   Database   │
│             │     │                  │     │              │
│  read SID   │     │  SELECT by ID    │     │  Return row  │
└─────────────┘     └──────────────────┘     └──────────────┘
      │                     │                       │
      │                     ▼                       │
      │             ┌──────────────────┐           │
      │             │ Decode haystack  │           │
      │             │ (Base64 if needed)│          │
      │             └──────────────────┘           │
      │                     │                       │
      ▼                     ▼                       ▼
┌─────────────┐     ┌──────────────────┐     ┌──────────────┐
│  Response   │◀────│  SessionStorage  │◀────│   Database   │
│             │     │                  │     │              │
│ write data  │     │  UPDATE record   │     │  Store row   │
└─────────────┘     └──────────────────┘     └──────────────┘

```

### Retry Mechanism

[](#retry-mechanism)

The `loadById()` method includes a retry mechanism (up to 5 attempts) for handling race conditions when creating new session records. This ensures reliability under concurrent access.

📚 API Reference
---------------

[](#-api-reference)

### SessionStorage

[](#sessionstorage-1)

```
class SessionStorage implements \SessionHandlerInterface
{
    public function __construct(
        string $host,
        string $dbName,
        string $username,
        ?string $password = null,
        ?string $table = null,
    );

    public function setTable(string $table): void;
    public function open($savePath, $sessionName): bool;
    public function close(): bool;
    public function read($id): string;
    public function write($id, $data): bool;
    public function destroy($id): bool;
    public function gc($maxlifetime): int|false;
}
```

### SessionExtension (Nette)

[](#sessionextension-nette)

Configuration schema:

OptionTypeRequiredDefaultDescription`host``string`No\*-MySQL host`dbName``string`No\*-Database name`username``string`No\*-Database username`password``string`No\*-Database password`table``string`No`core__session_storage`Table name\* Required unless Doctrine DBAL is available (credentials are then inherited automatically).

🐛 Troubleshooting
-----------------

[](#-troubleshooting)

### "Session was corrupted" Error

[](#session-was-corrupted-error)

This error appears when session data cannot be written due to encoding issues. The package attempts to re-encode using Base64, but if this also fails:

1. Check your MySQL character set configuration
2. Ensure the `haystack` column uses `utf8_unicode_ci` or `utf8mb4_unicode_ci`
3. Clear corrupted sessions: `DELETE FROM core__session_storage WHERE id = 'problematic_id'`

### "mb\_substr" Function Not Available

[](#mb_substr-function-not-available)

The error `Function "mb_substr" is not available` indicates the `mbstring` extension is not installed. Install it:

```
# Debian/Ubuntu
sudo apt-get install php-mbstring

# CentOS/RHEL
sudo yum install php-mbstring
```

### Session Not Persisting

[](#session-not-persisting)

1. Verify the handler is registered before `session_start()`
2. Check database credentials and connectivity
3. Ensure the session table exists with correct schema
4. Verify you're not in CLI mode (sessions are disabled in CLI)

👤 Author
--------

[](#-author)

**Jan Barášek**

- Website:
- GitHub:

📄 License
---------

[](#-license)

`baraja-core/session` is licensed under the MIT license. See the [LICENSE](https://github.com/baraja-core/session/blob/master/LICENSE) file for more details.

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance32

Infrequent updates — may be unmaintained

Popularity17

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 95.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~84 days

Recently: every ~116 days

Total

11

Last Release

1515d ago

PHP version history (4 changes)v1.0.0PHP &gt;=7.1.0

v1.2.0PHP &gt;=7.4.0

v1.3.0PHP ^7.4 || ^8.0

v1.4.0PHP ^8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3382204?v=4)[baraja](/maintainers/baraja)[@baraja](https://github.com/baraja)

---

Top Contributors

[![janbarasek](https://avatars.githubusercontent.com/u/4738758?v=4)](https://github.com/janbarasek "janbarasek (44 commits)")[![dependabot-preview[bot]](https://avatars.githubusercontent.com/in/2141?v=4)](https://github.com/dependabot-preview[bot] "dependabot-preview[bot] (2 commits)")

---

Tags

databasedoctrinehandlerstorage

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/baraja-core-session/health.svg)

```
[![Health](https://phpackages.com/badges/baraja-core-session/health.svg)](https://phpackages.com/packages/baraja-core-session)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[mongodb/mongodb

MongoDB driver library

1.6k64.0M546](/packages/mongodb-mongodb)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90340.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
