Skip to content

Instantly share code, notes, and snippets.

@nicolas-grekas
Last active March 5, 2020 21:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicolas-grekas/7d210d0f2559f085548f1591dd11c66a to your computer and use it in GitHub Desktop.
Save nicolas-grekas/7d210d0f2559f085548f1591dd11c66a to your computer and use it in GitHub Desktop.
A class to generate compliant "ulid"
<?php
class Ulid
{
private static $time = -1;
private static $rand = [];
public function generate(bool $lowercase = false)
{
if (\PHP_INT_SIZE !== 8) {
throw new \RuntimeException("Ulid::generate() requires a 64-bit PHP runtime." );
}
$time = (int) (1000 * microtime(true));
if ($time !== self::$time) {
self::$rand = unpack('Jhigh/Jlow', "\0\0\0".substr_replace(random_bytes(10), "\0\0\0", 5, 0));
self::$time = $time;
} elseif (1<<40 === ++self::$rand['low']) {
self::$rand['low'] = 0;
if (1<<40 === ++self::$rand['high']) {
self::$rand['low'] = self::$rand['high'] = (1<<40) - 1;
usleep(1000);
return self::generate($lowercase);
}
}
return strtr(
str_pad(base_convert($time, 10, 32), 10, '0', STR_PAD_LEFT)
.str_pad(base_convert(self::$rand['high'], 10, 32), 8, '0', STR_PAD_LEFT)
.str_pad(base_convert(self::$rand['low'], 10, 32), 8, '0', STR_PAD_LEFT)
, 'abcdefghijklmnopqrstuv', $lowercase ? 'abcdefghjkmnpqrstvwxyz' : 'ABCDEFGHJKMNPQRSTVWXYZ');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment