【问题标题】:PHP URL Shortening AlgorithmPHP URL 缩短算法
【发布时间】:2010-08-18 15:59:00
【问题描述】:

谁能推荐一种首选算法来缩短网址?我正在使用 PHP 进行编码。最初我想写一些东西,从一个字符开始,比如“a”并遍历请求,在数据库中创建记录,因此必须将字符增加到 b、c、d ... A、B 等等合适。

但是我突然意识到这个算法可能非常繁琐/笨拙,可能有更好的方法来做到这一点。

我在 Google 上阅读了一些内容,有些人似乎是通过数据库 ID 列的基本转换来实现的。这不是我太熟悉的东西。

有人可以详细说明并向我解释这是如何工作的吗?几个代码示例也会很棒。

我显然不想要一个完整的解决方案,因为我想自己学习,但只是一个关于如何工作的解释/伪代码会很好。

【问题讨论】:

    标签: php algorithm url url-shortener


    【解决方案1】:

    大多数缩短服务只使用一个计数器,每次输入都会递增,并将基数从 10 转换为 64。

    PHP 中的实现可能如下所示:

    function encode($number) {
        return strtr(rtrim(base64_encode(pack('i', $number)), '='), '+/', '-_');
    }
    function decode($base64) {
        $number = unpack('i', base64_decode(str_pad(strtr($base64, '-_', '+/'), strlen($base64) % 4, '=')));
        return $number[1];
    }
    
    $number = mt_rand(0, PHP_INT_MAX);
    var_dump(decode(encode($number)) === $number);
    

    encode 函数接受一个整数,将其转换为字节 (pack),使用 Base-64 编码 (base64_encode) 对其进行编码,修剪尾随填充 = (rtrim),并将字符+ 和/ 分别替换为- 和_ (strtr)。 decode 函数是 encode 的反函数,其作用正好相反(添加尾随填充除外)。

    strtr 的额外用途是将original Base-64 alphabet 转换为URL and filename safe alphabet,因为+ 和/ 需要使用百分比编码。

    【讨论】:

    • 感谢您的建议!现在有很多东西可以让我咬牙切齿。我将与 Base64 一起玩。谢谢。
    【解决方案2】:

    您可以使用 base_convert 函数将数据库 ID 从 10 转换为 36。

    <?php
       $id = 315;
       echo base_convert($id, 10, 36), "\n";
    ?>
    

    或者您可以重复使用下面页面中 cmets 中提出的一些想法:

    http://php.net/manual/en/function.base-convert.php

    【讨论】:

      【解决方案3】:

      假设你的 PRIMARY KEY 是一个 INT 并且它是 auto_increments,下面的代码会让你开始 =)。

      <?php
      
          $inSQL = "INSERT INTO short_urls() VALUES();";
          $inResult = mysql_query($inSQL);
          $databaseID = base_convert(mysql_insert_id(), 10, 36);
      
          // $databaseID is now your short URL
      
      ?>
      

      编辑:包括来自 HGF 答案的 base_convert。我忘记在原帖中使用 base_convert。

      【讨论】:

      • 非常感谢。我可以理解,但如果你只使用数据库 ID,你肯定会被限制为 0-9 的数字,所以只有 Base10?以某种方式使用a-zA-Z0-9不是更好吗?或者我有一个非常金发的时刻......
      【解决方案4】:

      我曾经通过类似于如何从十进制转换为十六进制的算法来打破 ID,但它将使用 62 个字符而不是十六进制将使用的 16 个字符。

      '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'
      

      示例:如果您更改 ID = 1234567890,您将获得 kv7yl1 作为您的密钥。

      【讨论】:

        【解决方案5】:

        我采用了“轻量级”解决方案。根据用户请求,我使用此 python 片段生成唯一标识符(检查 db 中的冲突):

        url_hash = base64.b64encode(os.urandom(int(math.ceil(0.75*7))))[:6]
        

        并将其存储在数据库中。

        【讨论】:

          【解决方案6】:

          原生 PHP base_convert() 适用于小范围的数字,但如果您确实需要编码较大的值,请考虑使用类似此处提供的实现,如果您只需提供更多合法字符,它将适用于 base 64 及以上用于编码。

          http://af-design.com/blog/2010/08/10/working-with-big-integers-in-php/

          【讨论】:

            【解决方案7】:

            这里试试这个方法:

            hash_hmac('joaat', "http://www.example.com/long/url/", "secretkey");
            

            它将为您提供适合专业网址缩短器的哈希值,例如:'142ecd53'

            【讨论】:

            • As of PHP7.2.0 - 已禁用非加密哈希函数(adler32、crc32、crc32b、fnv132、fnv1a32、fnv164、fnv1a64、joaat)。
            猜你喜欢
            • 1970-01-01
            • 2011-06-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多