12

URL短縮に使用する推奨アルゴリズムを誰か推奨できますか? PHPを使ってコーディングしています。最初は、「a」などの文字で始まり、リクエストを繰り返し処理し、データベースにレコードを作成するため、文字を b、c、d ... A、B などにインクリメントする必要があるものを書くことを考えました。適切な。

しかし、このアルゴリズムはかなり重く/不器用である可能性があり、それを行うためのより良い方法がある可能性があることに気づきました。

Google で少し読んだところ、データベースの ID 列からの基数変換を行っている人もいるようです。これは私がよく知っていることではありません。

誰かがこれがどのように機能するかを詳しく説明してくれますか? いくつかのコード例も素晴らしいでしょう。

私は自分でそれを学びたいので、完全な解決策は明らかに望んでいませんが、これがどのように機能するかについての説明/疑似コードは素晴らしいでしょう.

4

7 に答える 7

17

ほとんどの短縮サービスは、エントリごとにインクリメントされるカウンターを使用し、基数を 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で置き換えます ( )。関数は逆関数であり、正反対のことを行います (末尾のパディングの追加を除く) ​​。+/-_strtrdecodeencode

の追加の使用法は、元の Base-64 アルファベットURL およびファイル名に安全なアルファベットstrtr変換することであり、パーセンテージ エンコーディングでエンコードする必要があります。+/

于 2010-08-18T17:00:25.897 に答える
4

base_convert 関数を使用して、データベース ID を使用して 10 から 36 への基本変換を行うことができます。

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

または、次のページのコメントに示されているアイデアの一部を再利用できます。

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

于 2010-08-18T16:16:18.127 に答える
2

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を忘れました。

于 2010-08-18T16:08:27.583 に答える
1

私は「軽い」解決策を採用しました。ユーザーの要求に応じて、次の python スニペットを使用して一意の識別子を生成します (db での競合をチェックします)。

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

そしてそれをdbに保存します。

于 2010-08-18T16:32:58.907 に答える
1

以前は、10 進数から 16 進数に変換する方法と同様のアルゴリズムで ID を分割していましたが、16 進数が使用する 16 文字ではなく 62 文字を使用します。

'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が取得されます。

于 2010-08-18T16:17:44.113 に答える
1

ネイティブ PHP の base_convert() は小さな範囲の数値に対しては適切に機能しますが、大きな値をエンコードする必要がある場合は、ここで提供されている実装のようなものを使用することを検討してください。これは、エンコーディングに適切な文字を追加するだけで、base 64 以降で機能します。 .

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

于 2010-08-18T17:18:08.090 に答える