pimbay-php/sequence-random-doctrine

Doctrine DBAL implementation of RandomSequenceInterface for the PimBay Sequence Stack (MySQL, MariaDB, PostgreSQL, SQLite, MSSQL).

Maintainers

Package info

codeberg.org/pimbay-php/sequence-random-doctrine

Homepage

Issues

Documentation

pkg:composer/pimbay-php/sequence-random-doctrine

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

v1.0.0 2026-05-24 15:28 UTC

This package is auto-updated.

Last update: 2026-05-24 15:41:02 UTC


README

Latest Version on Packagist PHP Version License Code Coverage

Doctrine DBAL implementation of RandomSequenceInterface for the PimBay Sequence Stack. Supports MySQL, MariaDB, PostgreSQL, SQLite, and MSSQL.

Code uniqueness is guaranteed by a UNIQUE(group_id, code) database constraint — no application-level locking required.

Installation

composer require pimbay-php/sequence-random-doctrine

Usage

Schema setup

use PimBay\Sequence\Random\Doctrine\SchemaManager;

$schema = new SchemaManager($connection);
$schema->createTable();                        // default table: pimbay_sequence_random
$schema->createTable('my_custom_table');       // custom table name

createTable() is idempotent — safe to call on every deploy.

Basic usage

use PimBay\Sequence\Random\Doctrine\RandomSequence;
use PimBay\Sequence\Random\Doctrine\Adapter\DriverDetectingAdapter;

$adapter = new DriverDetectingAdapter($connection);
$sequence = new RandomSequence($connection, $adapter, $generatorFactory);

// Create a sequence — binds a code generator to a group+name pair
$result = $sequence->createSequence('vouchers', 'christmas_2026', $generator, ['channel' => 'email']);

// Generate unique codes
$code = $sequence->nextCode('vouchers', 'christmas_2026', context: ['country' => 'SK'], metadata: ['batch' => 'q4']);

// Reserve a fixed code — prevents random generation of the same code
$sequence->insertCode('vouchers', 'christmas_2026', 'VIANOCE2026', ['source' => 'import_2026_q1']);

// Check existence — scoped to group
$exists = $sequence->exists('vouchers', 'VIANOCE2026');

// Read current sequence state
$state = $sequence->getCurrent('vouchers', 'christmas_2026');
// $state->group, $state->name, $state->metadata, $state->createdAt, $state->generatorConfig

Adapters

DriverDetectingAdapter resolves the correct adapter from the DBAL driver automatically:

use PimBay\Sequence\Random\Doctrine\Adapter\DriverDetectingAdapter;

// Auto-detects driver and picks the right adapter
$adapter = new DriverDetectingAdapter($connection);

// Custom table name — must match the table used in RandomSequence
$adapter = new DriverDetectingAdapter($connection, 'my_custom_table');

// Custom adapter map — extend with your own driver
$adapter = new DriverDetectingAdapter($connection, 'my_table', [MyOracleDriver::class => MyOracleAdapter::class]);

Concrete adapters can be used directly:

use PimBay\Sequence\Random\Doctrine\Adapter\MysqlAdapter;
use PimBay\Sequence\Random\Doctrine\Adapter\PostgresAdapter;
use PimBay\Sequence\Random\Doctrine\Adapter\SqliteAdapter;
use PimBay\Sequence\Random\Doctrine\Adapter\MssqlAdapter;

$adapter = new MysqlAdapter($connection, $tableName);

Custom table name

Pass the same table name consistently to RandomSequence, DriverDetectingAdapter, and SchemaManager:

$tableName = 'my_voucher_sequences';

$schema = new SchemaManager($connection);
$schema->createTable($tableName);

$adapter = new DriverDetectingAdapter($connection, $tableName);
$sequence = new RandomSequence($connection, $adapter, $generatorFactory, $tableName);

Exception handling

All exceptions implement SequenceExceptionInterface:

use PimBay\Sequence\Exception\SequenceExceptionInterface;
use PimBay\Sequence\Exception\SequenceNotFoundException;
use PimBay\Sequence\Exception\SequenceAlreadyExistsException;
use PimBay\Sequence\Exception\SequenceCollisionException;
use PimBay\Sequence\Exception\CodeAlreadyExistsException;

try {
    $code = $sequence->nextCode('vouchers', 'christmas_2026');
} catch (SequenceCollisionException $e) {
    // max attempts exceeded — generator alphabet too small or sequence exhausted
} catch (SequenceNotFoundException $e) {
    // sequence does not exist — createSequence() was not called
} catch (SequenceExceptionInterface $e) {
    // catch-all for any sequence exception
}

Doctrine Migrations

applyToSchema() integrates with Doctrine Migrations:

use PimBay\Sequence\Random\Doctrine\SchemaManager;

$schema = new Schema();
(new SchemaManager($connection))->applyToSchema($schema);

Constraint names match the SQL schema files (uq_{table}_*, fk_{table}_*) — no diff noise on subsequent migrations.

Raw SQL access

SQL constants are available for custom migration tooling:

use PimBay\Sequence\Random\Doctrine\SchemaManager;

// Per-driver statement arrays
SchemaManager::MYSQL_CREATE_TABLE_STATEMENTS;
SchemaManager::POSTGRES_CREATE_TABLE_STATEMENTS;
SchemaManager::SQLITE_CREATE_TABLE_STATEMENTS;
SchemaManager::MSSQL_CREATE_TABLE_STATEMENTS;

// Full SQL string (statements joined with \n\n)
$sql = (new SchemaManager($connection))->getCreateTableSql('my_table');

Test Matrix

PHP 8.3PHP 8.4PHP 8.5
DBAL 2
DBAL 3
DBAL 4
MariaDB 11
SQLite

DBAL 2 tested on PHP 8.3 only — EOL since early 2026. MySQL, PostgreSQL, and MSSQL covered by unit tests with DBAL Connection mock.

Packages in the stack

PackageDescription
pimbay/sequence-random-sqlSQL snippets for random sequence adapters
pimbay-php/sequenceInterfaces, results, exceptions
pimbay-php/sequence-formatterPattern formatter, code generator, alphabet
pimbay-php/sequence-random-pdoPDO adapter for random sequences
pimbay-php/sequence-random-doctrineThis package — Doctrine DBAL adapter

License

Public domain — Unlicense

Created by Jan Sarmir · No conditions · No copyright