PHP URL Shortening Algorithm

北战南征 提交于 2019-11-30 05:09:36

Most shortening services just use a counter that is incremented with every entry and convert the base from 10 to 64.

An implementation in PHP could look like this:

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);

The encode function takes an integer number, converts it into bytes (pack), encodes it with the Base-64 encoding (base64_encode), trims the trailing padding = (rtrim), and replaces the characters + and / by - and _ respectively (strtr). The decode function is the inverse function to encode and does the exact opposite (except adding trailing padding).

The additional use of strtr is to translate the original Base-64 alphabet to the URL and filename safe alphabet as + and / need to be encoded with the Percentage-encoding.

You can use base_convert function to do a base convertion from 10 to 36 with the database IDs.

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

Or you can reuse some of the ideas presented in the comments on the page bellow:

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

i used to break ID by algorithm similar with how to convert from decimal to hex, but it will use 62 character instead of 16 character that hex would use.

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

example : if you will change ID = 1234567890 you will get kv7yl1 as your a key.

Assuming your PRIMARY KEY is an INT and it auto_increments, the following code will get you going =).

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

?>

EDIT: Included the base_convert from HGF's answer. I forgot to base_convert in the original post.

I adopted a "light" solution. On user request I generate a unique identifier (checking for conflicts in db) with this python snipplet:

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

and store it in db.

The native PHP base_convert() works well for small ranges of numbers, but if you really need to encode large values, consider using something like the implementation provided here which will work to base 64 and beyond if you simply provide more legal characters for the encoding.

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

AWC

Here try this method :

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

It will provide you with hash value fit for a professional url shortener, e.g: '142ecd53'

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!