Skip to content

Instantly share code, notes, and snippets.

@ranaroussi
Created March 15, 2023 21:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ranaroussi/ec91bc1eec21703f7e7cf78ff748425f to your computer and use it in GitHub Desktop.
Save ranaroussi/ec91bc1eec21703f7e7cf78ff748425f to your computer and use it in GitHub Desktop.
Simple PHP implementation of Nanoid, secure URL-friendly unique ID generator
<?php
/**
* Generate secure URL-friendly unique ID.
* By default, ID will have 21 symbols to have same collisions probability
* as UUID v4.
*
* @param integer $len The length of the ID to generate.
* @param mixed $entropy balanced, true (max), false (min)
* @param string $alphabet The characters to use in the ID.
*
* @return string random string of characters
*/
function generateNanoId(int $len = 21, mixed $entropy = 'balanced', string $alphabet = '_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string
{
$id = '';
$alphabet_len = strlen($alphabet);
if ($entropy === false || $entropy == 'balanced') {
$tolen = $entropy == 'balanced' ? $len / 2 : $len;
for ($i = 0; $i < $tolen; $i++) {
$id .= $alphabet[random_int(0, $alphabet_len - 1)];
}
if ($entropy != 'balanced') {
return $id;
}
}
$mask = (2 << (int) (log($alphabet_len - 1) / M_LN2)) - 1;
$step = (int) ceil(1.6 * $mask * $len / $alphabet_len);
while (true) {
$bytes = unpack('C*', random_bytes($len));
for ($i = 1; $i <= $step; $i++) {
$byte = $bytes[$i]&$mask;
if (isset($alphabet[$byte])) {
$id .= $alphabet[$byte];
if (strlen($id) === $len) {
return $id;
}
}
}
}
}
// usage:
$nanoId = generateNanoId();
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment