如何创建尽可能短的URL唯一id


How to create URL-able unique id that is as short as possible?

对于我的域,我正在尝试开发一个ID生成器,该生成器创建一个唯一的ID,然后可以将其用于短链接(就像URL短链接器一样)。

我曾想过使用md5()uniqueid()来创建ID。但为了使URL尽可能短,这并不明智,因为它会传递大量的ID,因此字符串/ID会变得更长,而没有任何必要。

现在PHP的字符串增量提供了一种有趣的方法。我可以做:

$d = 'A08';
for ($n=0; $n<60; $n++) {
    echo ++$d . PHP_EOL;
}
// Outputs: A09 .. A68

但这只给了我从A09A68的所有字符串。所以我设置了$d = '000',以便从那里开始。但现在它只返回从160的整数,而不是字符串。

如何强制PHP从000通过AAA递增到ZZZ

可以说,我想要一个从09AZ以及az的id。

0, 1, 2, .., 9, A, .., Z, a, .., z

然后第二个字符应添加到id:

00, 01, 02, .., 09, 0A, .., 0Z, 0a, .., 0z

我在http://filepublicator.com.我的解决方案是,每个帖子都有自己唯一的增量id(就像你通常给它们的一样:1、2、3等),还有一个转换为基数62的id副本。

然后我使用这个基础62副本作为url。关于这一点,SO上还有另一条线索:将基数10转换为基数62(a-zA-Z0-9)

我采用了这种方法,首先生成一个真实的id,然后将其转换为基数62,因为这样我就知道我有一个唯一的id,而无需针对我现有的帖子进行测试,而且它可以很容易地在运行中转换为我的真实id。

理论上,有人可以很容易地找到我创建URL的方法,并尝试循环浏览我的所有页面,但如果你想让帖子隐藏起来,并且在没有密码保护的情况下很难找到短URL,那就不是办法了。

这是Eineki在该线程中编写的方法:

function toBase($num, $b=62) {
  $base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $r = $num  % $b ;
  $res = $base[$r];
  $q = floor($num/$b);
  while ($q) {
    $r = $q % $b;
    $q =floor($q/$b);
    $res = $base[$r].$res;
  }
  return $res;
}
function to10( $num, $b=62) {
  $base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $limit = strlen($num);
  $res=strpos($base,$num[0]);
  for($i=1;$i<$limit;$i++) {
    $res = $b * $res + strpos($base,$num[$i]);
  }
  return $res;
}

测试

for ($i = 0; $i<1000000; $i++) {
  $x =  toBase($i);
  $y =  to10($x);
  if ($i-$y)
    echo "'n$i -> $x -> $y";
}

您可以生成AAA-ZZZ,如下所示:

for($key = 'AAA'; $key != 'ZZZ'; $key++) {
    echo $key;
}

希望我能正确理解你的问题。

编辑:

$last_key = 'ZZZ';
for($key = 1; $key != $last_key; $key++) {
    echo is_int($key) ? sprintf('%03d', $key) : $key;
    if($key == 999) { $key = 'AAA'; }
}

输出:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
...
...
998
999

紧随其后的是

AAB
AAC
AAD
AAE
AAF
AAG
AAH
AAI
AAJ
AAK
AAL
AAM
AAN
AAO
AAP
AAQ
AAR
AAS
AAT
AAU
...
...
ZZX
ZZY

返回结果"a01"-"cw00"

<?php
   $d = 'a00';
   for ($n=0; $n < 10000; $n++) {
    echo ++$d . PHP_EOL;
   }
?>

不太确定这是否是你想要的。。。