inanepain / id-forge
A lightweight & versatile library for generating and encoding unique identifiers. It provides fast, secure, and flexible solutions for modern applications.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
pkg:composer/inanepain/id-forge
Requires
- php: >=8.4
- inanepain/stdlib: >=0.7.1 || dev-master || dev-develop
This package is auto-updated.
Last update: 2026-02-19 23:24:41 UTC
README
Table of Contents
inanepain/id-forge- Install
- 1. Quickstart
- 2. Modules
- 3. Encoders
- 4. Generators
- 5. Configuration
- 6. Factories
- 7. Example
- 8. Error handling
- 9. When to use which generator
inanepain/id-forge
A lightweight & versatile library for generating and encoding unique identifiers. It provides fast, secure, and flexible solutions for modern applications.
-
Reversible encoders (
Base32,Base58,Base64) via a commonEncoderInterface -
Several ID generators (
UUIDv4,ULID,Nanoid, Snowflake-like IDs) via a commonIdGeneratorInterface -
Simple configuration of objects and factory helpers
| Tip |
All examples target PHP 8.2+ (the codebase is PHP 8.4-ready). Namespaces are rooted under Inane\IdForge.
|
Install
$ composer require inanepain/id-forge
1. Quickstart
Generate a few IDsuse Inane\IdForge\IdGeneratorFactory; use Inane\IdForge\EncoderFactory; $uuid = IdGeneratorFactory::createUUID()->generate(); $ulid = IdGeneratorFactory::createULID()->generate(); $nanoid = IdGeneratorFactory::createNanoid()->generate(); $snow = IdGeneratorFactory::createSnowflake(1, 2)->generate(); $base58 = EncoderFactory::createBase58(); $encoded = $base58->encode($ulid); $decoded = $base58->decode($encoded);
2. Modules
3. Encoders
This module provides reversible string encoders that share a simple contract, EncoderInterface. Implementations cover Base32, Base58, and Base64 (including a URL-safe variant).
3.1. Contracts and base classes
3.1.1. Inane\IdForge\Interface\EncoderInterface
Contract for reversible string encoders:
-
encode(string $data): string— converts binary-safe input to an encoded string -
decode(string $data): string— converts an encoded string back to the original binary data
Implementations must be deterministic and satisfy decode(encode($x)) === $x for valid input. Invalid input should raise Inane\Stdlib\Exception\InvalidArgumentException (or a domain-specific exception).
3.1.2. Inane\IdForge\Encoder\AbstractEncoder
A small base class that stores an EncoderConfig and exposes helpers:
-
getAlphabet(): string -
getAlphabetLength(): int
Concrete encoders (Base32/58/64) extend this class.
3.2. Implementations
3.2.1. Base32
Namespace: Inane\IdForge\Encoder\Base32Encoder
-
Alphabet: configurable (RFC 4648 by default when using
EncoderFactory::createBase32()) -
Padding: not applied; trailing zero bits are used to complete the last 5-bit group
-
Errors: throws
InvalidArgumentExceptionif a character is not in the alphabet duringdecode()
use Inane\IdForge\EncoderFactory; $base32 = EncoderFactory::createBase32(); $enc = $base32->encode("\x00\xFFHello"); $bin = $base32->decode($enc);
3.2.2. Base58
Namespace: Inane\IdForge\Encoder\Base58Encoder
-
Alphabet: configurable (Bitcoin alphabet via
EncoderFactory::createBase58()) -
Preserves leading zero bytes as leading first-alphabet characters
-
Errors: throws
InvalidArgumentExceptionfor unknown characters duringdecode()
use Inane\IdForge\EncoderFactory; $base58 = EncoderFactory::createBase58(); $enc = $base58->encode("\0\0payload"); $bin = $base58->decode($enc);
3.2.3. Base64
Namespace: Inane\IdForge\Encoder\Base64Encoder
-
Standard Base64 via
encode()/decode() -
URL-safe helpers:
urlEncode()replaces+//with-/_and strips padding;urlDecode()restores and decodes -
Errors:
decode()andurlDecode()throwInvalidArgumentExceptionfor invalid Base64 input
use Inane\IdForge\EncoderFactory; $base64 = EncoderFactory::createBase64(); $token = $base64->urlEncode(random_bytes(16)); $bytes = $base64->urlDecode($token);
3.3. Configuration
Encoders accept Inane\IdForge\Config\EncoderConfig which holds:
-
alphabet: string -
alphabetLength: int(precomputed)
Use EncoderFactory for sensible defaults or construct encoders manually with a custom alphabet.
3.4. Exceptions
-
Inane\Stdlib\Exception\InvalidArgumentException— invalid input duringdecode()
3.5. See also
4. Generators
IdForge includes several generators that implement a common contract, IdGeneratorInterface. Each generator focuses on a different trade-off: interoperability (UUID), sortability (ULID, Snowflake), or brevity and URL-friendliness (Nanoid).
4.1. Contract and base class
4.1.1. Inane\IdForge\Interface\IdGeneratorInterface
-
generate(): string— create a new identifier as a string
Implementations should be fast, low-collision, and safe to use concurrently.
4.1.2. Inane\IdForge\Generator\AbstractIdGenerator
Provides helpers shared by all generators:
-
getRandomBytes(int $length): string— cryptographically secure random bytes (can throwRandom\RandomException) -
getTimestamp(): int— current UNIX timestamp in milliseconds
4.2. Implementations
4.2.1. UUIDv4
Namespace: Inane\IdForge\Generator\UUIDGenerator
-
RFC 4122 UUID version 4
-
Format: canonical 36-char string
8-4-4-4-12 -
Helpers:
-
isValid(string $uuid): bool -
toBase64(string $uuid, Base64Encoder $base64): string— URL-safe Base64 (no padding) -
fromBase64(string $b64, Base64Encoder $base64): string— back to canonical string -
Errors:
toBase64()throwsInvalidArgumentExceptionfor invalid input
use Inane\IdForge\IdGeneratorFactory; use Inane\IdForge\EncoderFactory; $uuid = IdGeneratorFactory::createUUID()->generate(); $base64 = EncoderFactory::createBase64(); $b64 = IdGeneratorFactory::createUUID()->toBase64($uuid, $base64); $uuid2 = IdGeneratorFactory::createUUID()->fromBase64($b64, $base64);
4.2.2. ULID
Namespace: Inane\IdForge\Generator\ULIDGenerator
-
26-char Crockford Base32, lexicographically sortable
-
Structure: 48-bit timestamp + 80 bits randomness
-
Monotonic mode ensures strict ordering within the same millisecond
-
Key methods:
-
__construct(?EncoderConfig $config = null, bool $monotonic = false) -
generate(?int $timestamp = null): string -
decodeTimestamp(string $ulid): int -
decode(string $ulid): array{timestamp:int, random:string} -
toEncoded(EncoderInterface $encoder): string -
Errors:
InvalidArgumentExceptionfor bad characters/length;Random\RandomExceptionfor entropy issues
use Inane\IdForge\IdGeneratorFactory; $ulid = IdGeneratorFactory::createULID()->generate();Monotonic ULID
use Inane\IdForge\Generator\ULIDGenerator; use Inane\IdForge\Config\EncoderConfig; $mono = new ULIDGenerator(new EncoderConfig('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), true); $a = $mono->generate(); $b = $mono->generate(); // guaranteed $a < $b when in same ms
4.2.3. Nanoid
Namespace: Inane\IdForge\Generator\NanoidGenerator
-
Short, URL-friendly random IDs
-
Constructor:
__construct(string $alphabet = '0-9a-zA-Z', int $size = 21) -
generate(): string
use Inane\IdForge\IdGeneratorFactory; $id = IdGeneratorFactory::createNanoid()->generate();
4.2.4. Snowflake-like
Namespace: Inane\IdForge\Generator\SnowflakeIdGenerator
-
64-bit composed numeric ID (as a string): timestamp + datacenter + worker + sequence
-
Configured via
SnowflakeConfig(epoch, bit allocations for worker/datacenter/sequence) -
Methods:
-
__construct(int $workerId = 0, int $datacenterId = 0, ?SnowflakeConfig $config = null) -
generate(): string -
toEncoded(EncoderInterface $encoder): string -
Behavior: on sequence overflow within the same millisecond, waits for the next millisecond
-
Errors:
RuntimeExceptionif the clock moves backwards;InvalidArgumentExceptionfor out-of-range worker/datacenter
use Inane\IdForge\IdGeneratorFactory; $gen = IdGeneratorFactory::createSnowflake(workerId: 1, datacenterId: 2); $id = $gen->generate();
4.3. See also
5. Configuration
This module documents the small configuration objects that accompany encoders and generators.
5.1. EncoderConfig
Namespace: Inane\IdForge\Config\EncoderConfig
Holds the alphabet used by encoders and caches its length.
Fields-
alphabet: string— characters used by the encoding -
alphabetLength: int— cached length of the alphabet
-
__construct(string $alphabet)— set the alphabet and precompute its length -
getAlphabet(): string -
getAlphabetLength(): int
use Inane\IdForge\Config\EncoderConfig; use Inane\IdForge\Encoder\Base32Encoder; $config = new EncoderConfig('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'); $encoder = new Base32Encoder($config);
5.2. SnowflakeConfig
Namespace: Inane\IdForge\Config\SnowflakeConfig
Controls the epoch and bit allocations for Snowflake-like IDs.
Fields-
epoch: int— custom epoch in milliseconds (default: 1609459200000, 2021-01-01) -
workerIdBits: int— bits for worker/node id (default: 5) -
datacenterIdBits: int— bits for datacenter id (default: 5) -
sequenceBits: int— bits for per-millisecond sequence (default: 12)
-
__construct(int $epoch = 1609459200000, int $workerIdBits = 5, int $datacenterIdBits = 5, int $sequenceBits = 12) -
Getters:
-
getEpoch(): int -
getWorkerIdBits(): int -
getDatacenterIdBits(): int -
getSequenceBits(): int
use Inane\IdForge\Generator\SnowflakeIdGenerator; use Inane\IdForge\Config\SnowflakeConfig; $config = new SnowflakeConfig(epoch: 1700000000000, workerIdBits: 6, datacenterIdBits: 4, sequenceBits: 12); $gen = new SnowflakeIdGenerator(workerId: 3, datacenterId: 1, config: $config); $id = $gen->generate();
5.3. See also
6. Factories
Factory helpers provide convenient, opinionated constructors for common encoders and generators.
6.1. EncoderFactory
Namespace: Inane\IdForge\EncoderFactory
Creates encoder instances with sensible default alphabets.
API-
createBase32(): Base32Encoder— RFC 4648 alphabetA-Z2-7 -
createBase58(): Base58Encoder— Bitcoin alphabet (no0,O,I,l) -
createBase64(): Base64Encoder— Standard Base64 alphabet
use Inane\IdForge\EncoderFactory; $base32 = EncoderFactory::createBase32(); $base58 = EncoderFactory::createBase58(); $base64 = EncoderFactory::createBase64();
6.2. IdGeneratorFactory
Namespace: Inane\IdForge\IdGeneratorFactory
Creates generator instances with defaults and safe validation where applicable.
API-
createNanoid(string $alphabet = '0-9a-zA-Z', int $size = 21): NanoidGenerator -
createSnowflake(int $workerId = 0, int $datacenterId = 0, ?SnowflakeConfig $config = null): SnowflakeIdGenerator -
createUUID(): UUIDGenerator -
createULID(?EncoderConfig $config = null): ULIDGenerator
use Inane\IdForge\IdGeneratorFactory; $uuid = IdGeneratorFactory::createUUID()->generate(); $ulid = IdGeneratorFactory::createULID()->generate(); $nanoid = IdGeneratorFactory::createNanoid()->generate(); $snow = IdGeneratorFactory::createSnowflake(workerId: 1, datacenterId: 2)->generate();
6.3. See also
7. Example
Some examplesuse Inane\IdForge\Config\EncoderConfig; use Inane\IdForge\Config\SnowflakeConfig; use Inane\IdForge\Encoder\AbstractEncoder; use Inane\IdForge\EncoderFactory; use Inane\IdForge\Generator\AbstractIdGenerator; use Inane\IdForge\IdGeneratorFactory; // Example usage try { // Create encoders via factory $base32 = EncoderFactory::createBase32(); $base58 = EncoderFactory::createBase58(); $base64 = EncoderFactory::createBase64(); // Create ID generators via factory $nanoid = IdGeneratorFactory::createNanoid(); $snowflake = IdGeneratorFactory::createSnowflake(1, 1); $uuid = IdGeneratorFactory::createUUID(); $ulid = IdGeneratorFactory::createULID(); // Base32 $base32Encoded = $base32->encode('Hello'); echo "Base32 Encoded: $base32Encoded\n"; echo 'Base32 Decoded: ' . $base32->decode($base32Encoded) . "\n"; echo PHP_EOL; // Base58 $base58Encoded = $base58->encode('Hello'); echo "Base58 Encoded: $base58Encoded\n"; echo 'Base58 Decoded: ' . $base58->decode($base58Encoded) . "\n"; echo PHP_EOL; // Base64 $base64Encoded = $base64->urlEncode('Hello'); echo "Base64 URL Encoded: $base64Encoded\n"; echo 'Base64 URL Decoded: ' . $base64->urlDecode($base64Encoded) . "\n"; echo PHP_EOL; // Nanoid echo 'Nanoid: ' . $nanoid->generate() . "\n"; echo PHP_EOL; // Snowflake ID $snowflakeId = $snowflake->generate(); echo "Snowflake ID: $snowflakeId\n"; echo 'Snowflake ID (Base58): ' . $snowflake->toEncoded($base58) . "\n"; echo PHP_EOL; // UUID $uuidValue = $uuid->generate(); echo "UUID: $uuidValue\n"; $uuidBase64 = $uuid->toBase64($uuidValue, $base64); echo "UUID Base64: $uuidBase64\n"; echo 'UUID from Base64: ' . $uuid->fromBase64($uuidBase64, $base64) . "\n"; echo PHP_EOL; // ULID $ulidValue = $ulid->generate(); echo "ULID: $ulidValue\n"; echo 'ULID Timestamp: ' . $ulid->decodeTimestamp($ulidValue) . "\n"; echo 'ULID Base32: ' . $ulid->toEncoded($base32) . "\n"; echo PHP_EOL; // ULID $ulidValue = $ulid->generate(1761168799791); echo "ULID 2: $ulidValue\n"; echo 'ULID 2 Timestamp: ' . $ulid->decodeTimestamp($ulidValue) . "\n"; echo 'ULID 2 Base32: ' . $ulid->toEncoded($base32) . "\n"; } catch (Exception $e) { echo 'Error: ' . $e->getMessage() . "\n"; } // Add a New Encoder: class Base16Encoder extends AbstractEncoder { public function __construct() { parent::__construct(new EncoderConfig('0123456789ABCDEF')); } public function encode(string $data): string { return strtoupper(bin2hex($data)); } public function decode(string $data): string { return hex2bin($data); } } class Encoder2Factory { public static function createBase16(): Base16Encoder { return new Base16Encoder(); } } $base16 = Encoder2Factory::createBase16()->encode('Hello'); $text = Encoder2Factory::createBase16()->decode($base16); $line("Base16:encoded: $base16"); $line("Base16:decoded: $text"); // EncoderFactory::createBase16 = fn() => new Base16Encoder(); // Add a New ID Generator: class CustomIdGenerator extends AbstractIdGenerator { public function generate(): string { $timestamp = $this->getTimestamp(); $random = $this->getRandomBytes(8); return bin2hex($timestamp . $random); } } class IdGenerator2Factory { public static function createCustomId(): CustomIdGenerator { return new CustomIdGenerator(); } } $customId = IdGenerator2Factory::createCustomId()->generate(); $line("CustomID: $customId"); // IdGeneratorFactory::createCustomId = fn() => new CustomIdGenerator(); // Customize Snowflake Configuration: $customConfig = new SnowflakeConfig(1640995200000, 4, 4, 10); // Custom epoch, fewer bits $snowflake = IdGeneratorFactory::createSnowflake(1, 1, $customConfig); // Custom Alphabet for Nanoid: $nanoid = IdGeneratorFactory::createNanoid('0123456789abcdef', 12); // Hex-only, shorter length
8. Error handling
-
Most decoders will throw
Inane\Stdlib\Exception\InvalidArgumentExceptionwhen the input contains invalid characters or cannot be parsed. -
SnowflakeIdGenerator::generate()can throwInane\Stdlib\Exception\RuntimeExceptionif it detects a system clock moving backwards. -
Generators that rely on randomness may throw
Random\RandomExceptionfrom PHP core when entropy is not available.
9. When to use which generator
-
UUIDv4: Standard interoperable identifiers, not sortable, 36 chars.
-
ULID: 26-char, lexicographically sortable, timestamp + randomness; good for DB keys and logs.
-
Nanoid: Short, URL-friendly IDs with controllable alphabet and size.
-
Snowflake: Numeric IDs composed of timestamp + worker/datacenter + sequence; good for distributed systems that need k-sortable numbers.