2011-07-19 87 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