Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Ordinary UID

Universal Unique Identifier (OUID) implementation for OrdinaryPHP.

Installation

composer require ordinary/uid

Requirements

  • PHP 8.5 or higher

Features

  • Time-based: Includes timestamp with microsecond precision
  • Namespaced: Support for custom namespaces
  • Sortable: Chronologically sortable by design
  • Compact: Uses Crockford Base32 encoding for efficiency
  • Type-safe: Full PHP 8.5 type safety with property hooks

OUID Format

<namespace>-<time-seconds><time-microsecond>-<random-bytes>

Example: MYAPP-01J4K6M-8P0A-XYZW1234

  • namespace: Alphanumeric uppercase and underscore (e.g., MYAPP, MY_APP_123)
  • time-seconds: Crockford Base32 encoded Unix timestamp (7 chars, supports 100+ years)
  • time-microsecond: Crockford Base32 encoded microseconds (4 chars, 0-999999)
  • random-bytes: Crockford Base32 encoded random bytes (4 bytes)

Usage

Creating OUIDs

useOrdinary\Uid\Ouid;
useOrdinary\Uid\OuidGenerator;
usePsr\Clock\ClockInterface;
// Using the generator (recommended)$clock = newYourClockImplementation(); // PSR-20 Clock$generator = newOuidGenerator('MYAPP', $clock);
$ouid = $generator->generate();
// Manual creation$ouid = Ouid::create(
'MYAPP',
newDateTimeImmutable('now', newDateTimeZone('UTC')),
random_bytes(4)
);
// From string$ouid = Ouid::fromString('MYAPP-01J4K6M-8P0A-XYZW1234');
// NIL OUID$nil = Ouid::nil();

Accessing OUID Properties

$ouid = $generator->generate();
echo$ouid->value; // Full OUID stringecho$ouid->namespace; // "MYAPP"echo$ouid->datetime->format('Y-m-d H:i:s.u'); // Timestamp with microsecondsechobin2hex($ouid->randomBytes); // Random bytes as hex

Using with Objects

OUIDs can be embedded in value objects using property hooks for clean, type-safe access:

useOrdinary\Uid\HasOuid;
useOrdinary\Uid\HasOuidTrait;
useOrdinary\Uid\HasMutableOuid;
useOrdinary\Uid\HasMutableOuidTrait;
// Immutable OUID (can only be set once)class User implements HasOuid
{
use HasOuidTrait;
publicfunction__construct(Ouid$ouid)
{
$this->uid = $ouid->value; // Set via property
}
}
// Mutable OUID (can be changed anytime)class DraftPost implements HasMutableOuid
{
use HasMutableOuidTrait;
}
// Usage$user = newUser($generator->generate());
echo$user->uid; // String valueecho$user->getOuid()->value; // Ouid object$draft = newDraftPost();
$draft->uid = $generator->generate()->value;
echo$draft->getOuid()->namespace;

Deterministic Random (for testing)

useRandom\Engine\Xoshiro256StarStar;
usePsr\Clock\ClockInterface;
useDateTimeImmutable;
// Fixed clock for testing$clock = newclassimplements ClockInterface {
publicfunctionnow(): DateTimeImmutable {
returnnewDateTimeImmutable('2024-01-01 12:00:00');
}
};
$engine = newXoshiro256StarStar(12345); // Fixed seed$generator = newOuidGenerator('TEST', $clock, $engine);
$ouid1 = $generator->generate();
$ouid2 = $generator->generate();
// Different random bytes but deterministic sequence

Crockford Base32

This package uses Crockford Base32 encoding:

  • Character set: 0-9, A-Z (excluding I, L, O, U)
  • Case-insensitive decoding
  • Symbol equivalents: O/o0, I/i/L/l1
useOrdinary\Uid\CrockfordBase32;
$encoded = CrockfordBase32::encode(1234567);
$decoded = CrockfordBase32::decode($encoded);
$bytesEncoded = CrockfordBase32::encodeBytes("\x01\x02\x03\x04");
$bytesDecoded = CrockfordBase32::decodeBytes($bytesEncoded, 4);

Testing

vendor/bin/phpunit

License

MIT

About

Time-based, namespaced, sortable unique identifier (OUID) implementation for OrdinaryPHP.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages