2011-07-19 84 views
5

我想缩短我的网址,类似于tinyurl或任何其他网址缩短服务。我有以下类型的链接:用于缩短网址的PHP base_convert

localhost/test/link.php?id=1000001 
localhost/test/link.php?id=1000002 

在上面的链接的ID是从数据库行的自动递增的ID。 上面的链接映射,如:

localhost/test/1000001 
localhost/test/1000002 

现在,而不是使用上述长的ID,我想缩短他们。我发现我可以使用base_convert()函数。例如:

print base_convert(100000000, 10, 36); 

//output will be "1njchs" 

它看起来还不错,但我要问,如果有任何缺点使用此功能的(如:性能下降或任何其他)或者有没有更好的方法做同样的事情(如。使自己的函数生成随机ID字符串)?

谢谢。

回答

4

功能base_convert足够快,但如果你想做得更好,只需将编码的字符串存储在数据库中。

+1

感谢您的回复。刚刚得到另一个(相关)的问题。如果我用base_convert'base_convert(100000000,10,36);'转换一个数字,我可以通过更改函数中的基本顺序来取回原始数字,例如。 'base_convert(100000000,36,10);'。 – Roman

+1

是的,当然可以 - 'base_convert('1njchs',36,10)=='100000000''。 – Gedrox

3

随着base_convert()您可以将字符串转换为更短的代码 ,然后用intval()您在数据库中创建一个ID存储项目

我的代码片段: -

$code = base_convert("long string", 10, 36); 
$ID= intval($code ,36); 
0

不幸的是,我很不满意在这里和其他地方的答案是base_convert()和其他基于浮点的转换策略对于加密目的会失去不可接受的精度。而且,这些实现中的大多数都不能处理足够大的密码应用程序数量。以下提供了两种对大型基地应该安全的基地转换方法。例如,将base256(二进制字符串)转换为base85表示并返回。

使用GMP

您可以使用GMP的转化斌<的成本做到这一点 - >十六进制二不需要时间以及局限于base62。

<?php 
// Not bits, bytes. 
$data = openssl_random_pseudo_bytes(256); 

$base62 = gmp_strval(gmp_init(bin2hex($data), 16), 62); 
$decoded = hex2bin(gmp_strval(gmp_init($base62, 62), 16)); 

var_dump(strcmp($decoded, $data) === 0); // true 

纯PHP

如果你想超越base62到base85或轻微的性能提升,你需要像下面这样。

<?php 

/** 
* Divide a large number represented as a binary string in the specified base 
* and return the remainder. 
* 
* @param string &$binary 
* @param int $base 
* @param int $start 
*/ 
function divmod(&$binary, $base, $divisor, $start = 0) 
{ 
    /** @var int $size */ 
    $size = strlen($binary); 

    // Do long division from most to least significant byte, keep remainder. 
    $remainder = 0; 
    for ($i = $start; $i < $size; $i++) { 
     // Get the byte value, 0-255 inclusive. 
     $digit = ord($binary[$i]); 

     // Shift the remainder left by base N bits, append the last byte. 
     $temp = ($remainder * $base) + $digit; 

     // Calculate the value for the current byte. 
     $binary[$i] = chr($temp/$divisor); 

     // Carry the remainder to the next byte. 
     $remainder = $temp % $divisor; 
    } 

    return $remainder; 
} 

/** 
* Produce a base62 encoded string from a large binary number. 
* 
* @param string $binary 
* return string 
*/ 
function encodeBase62($binary) 
{ 
    $charMap = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    $base = strlen($charMap); 

    $size = strlen($binary); 
    $start = $size - strlen(ltrim($binary, "\0")); 

    $encoded = ""; 
    for ($i = $start; $i < $size;) { 
     // Do long division from most to least significant byte, keep remainder. 
     $idx = divmod($binary, 256, $base, $i); 

     $encoded = $charMap[$idx] . $encoded; 

     if (ord($binary[$i]) == 0) { 
      $i++; // Skip leading zeros produced by the long division. 
     } 
    } 

    $encoded = str_pad($encoded, $start, "0", STR_PAD_LEFT); 

    return $encoded; 
} 

/** 
* Produce a large binary number from a base62 encoded string. 
* 
* @param string $ascii 
* return string 
*/ 
function decodeBase62($ascii) 
{ 
    $charMap = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    $base = strlen($charMap); 

    $size = strlen($ascii); 
    $start = $size - strlen(ltrim($ascii, "0")); 

    // Convert the ascii representation to binary string. 
    $binary = ""; 
    for ($i = $start; $i < $size; $i++) { 
     $byte = strpos($charMap, $ascii[$i]); 
     if ($byte === false) { 
      throw new OutOfBoundsException("Invlaid encoding at offset '{$ascii[$i]}'"); 
     } 

     $binary .= chr($byte); 
    } 

    $decode = ""; 
    for ($i = 0; $i < $size;) { 
     // Do long division from most to least significant byte, keep remainder. 
     $idx = divmod($binary, $base, 256, $i); 

     $decode = chr($idx) . $decode; 

     if (ord($binary[$i]) == 0) { 
      $i++; // Skip leading zeros produced by the long division. 
     } 
    } 

    $decode = ltrim($decode, "\0"); 
    $decode = str_pad($decode, $start, "\0", STR_PAD_LEFT); 

    return $decode; 
} 

// Not bits, bytes. 
$data = openssl_random_pseudo_bytes(256); 

$base62 = encodeBase62($data); 
$decoded = decodeBase62($base62); 

var_dump(strcmp($decoded, $data) === 0); // true