【问题标题】:How to create URL-able unique id that is as short as possible?如何创建尽可能短的可 URL 唯一 ID?
【发布时间】:2014-01-04 23:27:15
【问题描述】:

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

我考虑过使用md5() 或uniqueid() 来创建该ID。但是为了使 URL 尽可能短,这样做并不明智,因为它传递了大量的 ID,因此字符串/ID 会毫无必要地变长。

现在PHP's string incrementation 提供了一种有趣的方式。我可以这样做:

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

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

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

可以这么说,我想要一个 ID,而不是从 0 到 9 到 A 到 Z 和 a 到 z。

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

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

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

【问题讨论】:

    标签: php increment sequential


    【解决方案1】:

    我在http://filepublicator.com 上做了类似的事情。我的解决方案是,每个帖子都有自己唯一的增量 id(就像您通常会给它们一样:1、2、3 等),以及将此 id 的副本转换为 base 62。

    然后我使用这个 base 62 副本作为 url。继承人关于这个的另一个线程: converting a number base 10 to base 62 (a-zA-Z0-9)

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

    理论上有人可以很容易地找出我创建网址的方法并尝试循环浏览我的所有页面,但是如果您正在寻找隐藏帖子并且很难找到没有密码保护的短网址是不可行的。

    这是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";
    }
    

    【讨论】:

      【解决方案2】:

      您可以按如下方式生成 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
      

      【讨论】:

      • 我正在寻找两者,000 到 999,然后是 AAA 到 ZZZ。
      • 是的,这样做了,但我正在寻找更复杂的东西,比如@Jens 的回答中引用的 Eineki 的回答。
      • 不幸的是我没那么老练:)
      • 我不是这个意思! :) 你的方法是一个很好的例子,它是一个清晰的方法。但是为了保持它的灵活性和可扩展性,我需要一种 - 比方说 - 更好的可维护方式。
      • 是的,我明白了。我也会一样,这更像是一种hacky方式。就像你说的,还有更复杂的方法。
      【解决方案3】:

      这将返回结果“a01”-“cw00”

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

      不太确定这是否是您要找的...

      【讨论】:

      • 其实没有。这是我的代码的回收加上使用小写。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 2011-08-22
      • 2022-01-20
      相关资源
      最近更新 更多