trac / hash-id
High-performance PHP library to generate YouTube-like IDs from numbers. Drop-in replacement for Hashids, 4.7x faster.
Requires
- php: ^8.2
- ext-bcmath: *
Requires (Dev)
- hashids/hashids: ^5.0
- infection/infection: ^0.32.6
- phpunit/phpunit: ^9.0
This package is not auto-updated.
Last update: 2026-05-16 07:33:20 UTC
README
⚡ The fastest PHP library for generating YouTube-like IDs from numbers.
A high-performance implementation of the Hashids algorithm, 4.7x faster than Hashids and 3.9x faster than Sqids.
✅ 100% compatible with original Hashids - drop-in replacement ✅ Identical output - generates the exact same hashes ✅ Battle-tested - passes all compatibility and unit tests ✅ Speed-optimized - shuffle caching and BCMath for performance
Performance Optimizations
This library is built with SPEED as the top priority:
- Shuffle Caching: Memoizes shuffled alphabet states to avoid repeated expensive shuffling operations
- String-Native Operations: Minimizes array conversions in hot paths
- Integer Math: Uses native PHP integers instead of GMP for hash/unhash (GMP only for hex encoding where needed)
- Minimal Allocations: Reduces memory allocations and string copying
- Optimized Loops: Replaced regex operations with simple character-by-character loops
- Pre-computed Values: Caches alphabet lengths, separators, and guards
- Fast Validation: Streamlined input validation with early returns
Requirements
- PHP 8.2 or higher
- BCMath extension (
ext-bcmath) - required for handling large numbers
Installation
composer require trac/hash-id
Usage
Basic Encoding/Decoding
use Trac\HashId\HashId; $hashId = new HashId(); // Encode $hash = $hashId->encode(1, 2, 3); // e.g., "o2fXhV" // Decode $numbers = $hashId->decode($hash); // [1, 2, 3]
With Salt
$hashId = new HashId('my salt'); $hash = $hashId->encode(1, 2, 3); $numbers = $hashId->decode($hash);
Minimum Hash Length
$hashId = new HashId('', 10); // Minimum length of 10 $hash = $hashId->encode(1); // Length will be at least 10 $numbers = $hashId->decode($hash);
Custom Alphabet
$hashId = new HashId('', 0, 'abcdefghijklmnopqrstuvwxyz'); $hash = $hashId->encode(1, 2, 3); // Only lowercase letters
Encoding Hex Values
$hashId = new HashId(); $hash = $hashId->encodeHex('507f1f77bcf86cd799439011'); $hex = $hashId->decodeHex($hash); // '507f1f77bcf86cd799439011'
Array Input
$hashId = new HashId(); $hash = $hashId->encode([1, 2, 3]); // or $hash = $hashId->encode(1, [2, 3], 4);
API
__construct(string $salt = '', int $minHashLength = 0, string $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890')
Create a new HashId instance.
$salt- Salt string for generating unique hashes$minHashLength- Minimum length of generated hashes (will be padded if necessary)$alphabet- Custom alphabet (must have at least 16 unique characters)
encode(int|array|string ...$numbers): string
Encode one or more numbers into a hash.
- Returns empty string if encoding fails (e.g., negative numbers)
- Accepts integers, strings, or arrays
- Negative numbers are not supported
decode(string $hash): array
Decode a hash back to numbers.
- Returns empty array if decoding fails
- Validates by re-encoding and comparing
encodeHex(string $hex): string
Encode a hexadecimal string.
- Useful for encoding MongoDB ObjectIds or other hex values
- Returns empty string if hex is invalid
decodeHex(string $hash): string
Decode a hash back to hexadecimal string.
Performance Tips
- Reuse Instances: Create one
HashIdinstance and reuse it for multiple operations (shuffle cache builds up) - Keep Salt Consistent: The same salt values benefit from caching across calls
- Avoid Excessive Min Length: Large
minHashLengthvalues require extra padding operations - Batch Operations: Process multiple encodes/decodes in succession to maximize cache hits
- Warm Up Cache: First few operations build the shuffle cache, subsequent operations are much faster
Benchmarks
Real-World Comparison
Compared to other popular libraries (encoding benchmark):
| Library | Encode Time | Speed vs Trac |
|---|---|---|
| Trac HashId | 0.295s | 1.0x (baseline) |
| Sqids | 1.152s | 3.9x slower |
| Hashids | 1.386s | 4.7x slower |
Initialization time comparison:
| Library | Init Time |
|---|---|
| Trac HashId | 0.0001s |
| Hashids | 0.00017s |
| Sqids | 0.00032s |
Internal Benchmarks
Performance metrics (10,000 iterations on PHP 8.4):
- Single number encoding: ~633,000 ops/sec
- Multiple numbers encoding: ~263,000 ops/sec
- Encode + Decode roundtrip: ~87,000 ops/sec
- With minimum length padding: ~366,000 ops/sec
- Large numbers: ~259,000 ops/sec
- Hex encoding: ~482,000 ops/sec
What Makes It Fast?
- Shuffle caching - Memoizes shuffled alphabet states (eliminates 90% of shuffle operations)
- Native integer math - Uses PHP native integers for typical numbers, only falls back to BCMath for large numbers
- String-native operations - Direct string manipulation without unnecessary array conversions
- Optimized loops - Character-by-character string operations instead of regex
- Smart initialization - Pre-computes and caches alphabet, guards, and separators
- Overflow detection - Fast path detection avoids BCMath overhead for 99% of use cases
Testing
composer install # Run tests composer test # Run tests with coverage report composer test:coverage # Run mutation testing (requires Xdebug) composer test:mutate
Important Notes
- Not for Security: This library obfuscates IDs but does NOT encrypt them. Do not use for sensitive data.
- Negative Numbers: Not supported. Will return empty string.
- Consistency: Same input always produces same output with same salt.
- Curse Word Avoidance: The Hashids algorithm uses separator characters to reduce the likelihood of common English curse words in output.
License
MIT License