pimbay-php/sequence

Contracts, results and exceptions for the PimBay Sequence Stack. Shared foundation for number and random sequence implementations.

Maintainers

Package info

codeberg.org/pimbay-php/sequence

Homepage

Issues

Documentation

pkg:composer/pimbay-php/sequence

Statistics

Installs: 5

Dependents: 2

Suggesters: 0

v1.1.0 2026-05-16 07:34 UTC

This package is auto-updated.

Last update: 2026-05-16 07:37:09 UTC


README

Latest Version on Packagist PHP Version License Code Coverage

Foundational interfaces, results and exceptions for the PimBay Sequence Stack. Shared foundation for number and random sequence implementations.

Installation

composer require pimbay-php/sequence

What is in this package

This package defines what sequence implementations must do. Concrete adapters live in separate packages and are injected at runtime.

Number sequences

use PimBay\Sequence\Number\NumberSequenceInterface;
use PimBay\Sequence\Number\NumberSequenceResult;
use PimBay\Sequence\Exception\SequenceNotFoundException;

NumberSequenceInterface — two methods:

// Atomic increment — creates sequence if it does not exist
$next = $sequence->nextNumber('invoice', '2026', initialValue: 1000);

// Read current value without incrementing — throws SequenceNotFoundException if missing
$result = $sequence->getCurrent('invoice', '2026');
// $result->currentValue, $result->metadata, $result->createdAt, $result->updatedAt

Random sequences

use PimBay\Sequence\Random\RandomSequenceInterface;
use PimBay\Sequence\Random\CodeGeneratorInterface;

RandomSequenceInterface — five methods:

// Create sequence with a bound code generator (generator config persisted in DB)
$sequence->createSequence('vouchers', 'christmas_2026', $generator);

// Generate unique code — retries internally on collision
// Pass runtime context for pattern tokens like {country}
$code = $sequence->nextCode('vouchers', 'christmas_2026', ['country' => 'SK']);

// Insert a fixed/manual code — reserves it, prevents random generation of the same code
$sequence->insertCode('vouchers', 'christmas_2026', 'VIANOCE2026');

// Read current sequence state without modifying it — throws SequenceNotFoundException if missing
$state = $sequence->getCurrent('vouchers', 'christmas_2026');
// $state->metadata, $state->createdAt, $state->updatedAt

// Check if code exists within the group
$exists = $sequence->exists('vouchers', 'VIANOCE2026');

CodeGeneratorInterface — implemented by pimbay-php/sequence-formatter:

public function generate(array $context = []): string;
public function toArray(): array;           // for JSON storage in DB

CodeGeneratorFactoryInterface — implemented by adapter packages or the application layer. Reconstructs a generator from its serialized toArray() configuration, with full access to the DI container for injecting dependencies such as NumberSequenceInterface or ClockInterface:

public function create(array $data): CodeGeneratorInterface;

Exceptions

All exceptions extend SequenceException implements SequenceExceptionInterface. To catch all sequence exceptions at once, use SequenceExceptionInterface:

use PimBay\Sequence\Exception\SequenceExceptionInterface;

try {
    $sequence->nextCode('vouchers', 'promo');
} catch (SequenceExceptionInterface $e) {
    // catches all sequence exceptions
}
ExceptionThrown by
SequenceNotFoundExceptionNumberSequenceInterface::getCurrent() or RandomSequenceInterface::getCurrent() on non-existent sequence
SequenceAlreadyExistsExceptioncreateSequence() on existing sequence
SequenceCollisionExceptionnextCode() after max attempts exceeded
CodeAlreadyExistsExceptioninsertCode() with duplicate code

Testing

This package ships with in-memory test doubles and a controllable clock for unit testing:

use PimBay\Sequence\Test\Support\InMemoryNumberSequence;
use PimBay\Sequence\Test\Support\InMemoryRandomSequence;
use PimBay\Sequence\Test\Support\MockClock;

// Controllable clock
$clock = new MockClock(new \DateTimeImmutable('2026-01-01'));
$clock->advance('+1 hour');

// In-memory number sequence
$numberSequence = new InMemoryNumberSequence($clock);
$next = $numberSequence->nextNumber('invoice', '2026', 1000);

// In-memory random sequence
$randomSequence = new InMemoryRandomSequence($clock);
$randomSequence->createSequence('vouchers', 'promo', $generator);
$code = $randomSequence->nextCode('vouchers', 'promo');
$state = $randomSequence->getCurrent('vouchers', 'promo');
// $state->metadata, $state->createdAt, $state->updatedAt

All test support classes are marked @internal — not intended for production use.

Packages in the stack

PackageDescription
pimbay-php/sequenceThis package — interfaces, results, exceptions
pimbay-php/sequence-formatterPattern formatter, code generator, alphabet
pimbay/sequence-number-sqlSQL snippets for number sequence adapters
pimbay-php/sequence-number-pdoPDO adapter — MySQL, MariaDB, PostgreSQL, SQLite
pimbay-php/sequence-number-pdo-mssqlPDO adapter — MSSQL
pimbay-php/sequence-random-pdoPDO adapter for random sequences

Test matrix

PHPStatus
8.3
8.4
8.5

License

Public domain — Unlicense

Created by Jan Sarmir · No conditions · No copyright