开发者

generating unique id's in php (for url shortener)

开发者 https://www.devze.com 2023-02-10 15:31 出处:网络
How can i generate a unique combinations of maximum 6 c开发者_Go百科haracters in php using (0 - 9), (a - z) and (A - Z)? How many possible combination those will be? (for example AAaa will be differen

How can i generate a unique combinations of maximum 6 c开发者_Go百科haracters in php using (0 - 9), (a - z) and (A - Z)? How many possible combination those will be? (for example AAaa will be different than Aaaa)?


Using base_convert($number, 10, 36) will not treat a-z differently from A-Z as is specified in the question. Custom functions are required.

Use an int column in your DB as the primary key that auto-increments on insert, then convert this ID from decimal to base-62 in your logic for the permalink (62 allows use of 0-9, a-z and A-Z).

When creating a new permalink:

<?php

/**
 * Convert decimal int to a base-62 string
 *
 * @param int $dec
 * @returns string
 */
function toBase62 ($dec) {

  // 0 is always 0
  if ($dec == 0)
    return "0";

  // this array maps decimal keys to our base-62 radix digits
  $values = array(
    "0", "1", "2", "3", "4", 
    "5", "6", "7", "8", "9", 
    "A", "B", "C", "D", "E",
    "F", "G", "H", "I", "J",
    "K", "L", "M", "N", "O",
    "P", "Q", "R", "S", "T",
    "U", "V", "W", "X", "Y", 
    "Z", "a", "b", "c", "d", 
    "e", "f", "g", "h", "i", 
    "j", "k", "l", "m", "n", 
    "o", "p", "q", "r", "s", 
    "t", "u", "v", "w", "x", 
    "y", "z"
  );

  // convert negative numbers to positive.
  $neg = $dec < 0;
  if ($neg)
    $dec = 0 - $dec;

  // do the conversion:
  $chars = array(); // this will store our base-62 chars

  while ($dec > 0) {

    $val = $dec % 62;

    $chars[] = $values[$val];

    $dec -= $val;
    $dec /= 62;

  }

  // add zero-padding:
  while (count($chars) < 6)
    $chars[] = '0';

  // convert to string
  $rv = implode( '' , array_reverse($chars) );

  // if input was negative:
  return $neg ? "-$rv" : $rv;

}


// Usage example:

// ... do mysql insert here and retrieve new insert_id into var $id ...

$permalink = toBase62($id);

?>

When decoding a requested permalink:

<?php

/**
 * Convert base-62 string to a decimal int
 *
 * @param string $str
 * @returns int on success, FALSE on failure
 */
function base62ToInt ($str) {

  // validate str:
  if ( ! preg_match('/^\-?[0-9A-Za-z]+$/', $str) )
    return FALSE; // not a valid string

  // 0 is always 0
  if ($str == "0" )
    return 0;

  // this array maps decimal keys to our base-62 radix digits
  $values = array(
    "0", "1", "2", "3", "4", 
    "5", "6", "7", "8", "9", 
    "A", "B", "C", "D", "E",
    "F", "G", "H", "I", "J",
    "K", "L", "M", "N", "O",
    "P", "Q", "R", "S", "T",
    "U", "V", "W", "X", "Y", 
    "Z", "a", "b", "c", "d", 
    "e", "f", "g", "h", "i", 
    "j", "k", "l", "m", "n", 
    "o", "p", "q", "r", "s", 
    "t", "u", "v", "w", "x", 
    "y", "z"
  );

  // flip $values so it maps base-62 digits to decimal values:
  $values = array_flip($values);

  // get chars from $str:
  $chars = str_split($str);

  // convert negative numbers to positive.
  $neg = $chars[0] == '-';

  if ($neg)
    array_shift($chars);

  // do the conversion:
  $val = 0;
  $i = 0;

  while ( count($chars) > 0 ) {

    $char = array_pop($chars);
    $val += ($values[$char] * pow(62, $i) );
    ++$i;

  }

  return $neg ? 0 - $val : $val;
}


// Usage example:

// ... assuming permalink has been put in a var called $permalink

$id = base62ToInt($permalink);

// ... now look up $id in DB

?>


My suggestion (particuarily if you are using a database to store them anyway) would be to let the database generate a unique row id using an autoincrement number in the database and then convert that number to your code, which is guaranteed to be unique since it was generated by the database.

In terms of generating the code from the number, my suggestion would be a simple substitution, so create a string with all your possible characters and convert your number to base 62 (count of all the characters) substituting a letter or number for each .

AaBbCcDd...0123456789

(on an aside, I would suggest removing lIioO01 as they all look very similar)

As suggested by Dan Grossman in the comment below, the following code will give you a very good approximation of what you want.

$code = base_convert($number, 10, 36);

This will give you a number based on the numbers and letters 0-9 and a-z.

0

精彩评论

暂无评论...
验证码 换一张
取 消