Tôi đang tìm một hàm PHP tạo ra một hàm băm ngắn từ một chuỗi hoặc một tệp, tương tự như các trang web rút ngắn URL đó như tinyurl.com
Hàm băm không được dài hơn 8 ký tự.
Tôi đang tìm một hàm PHP tạo ra một hàm băm ngắn từ một chuỗi hoặc một tệp, tương tự như các trang web rút ngắn URL đó như tinyurl.com
Hàm băm không được dài hơn 8 ký tự.
Alphabet::convert($hash, Alphabet::HEX, Alphabet::ALPHANUMERIC)
, bạn có thể giảm MD5 xuống 22 (từ 32) ký tự. Thay vào đó, những gì bạn muốn là mã hóa ID số nguyên của tệp (ví dụ từ cơ sở dữ liệu của bạn) bằng (new Id())->encode($id)
.
Câu trả lời:
Các dịch vụ rút ngắn URL thay vì sử dụng giá trị số nguyên tăng tự động (như ID cơ sở dữ liệu bổ sung) và mã hóa giá trị đó bằng Base64 hoặc các mã hóa khác để có nhiều thông tin hơn cho mỗi ký tự (64 thay vì chỉ 10 chữ số).
0
- 9
để biểu diễn một số, bạn có 10 giá trị có thể có cho mỗi ký tự được mã hóa (ld (10) ≈ 3,32 bit / ký tự). Tuy nhiên, nếu bạn đại diện cho cùng một số với các ký tự Base64, bạn có 64 giá trị có thể có cho mỗi ký tự được mã hóa (ld (64) = 6 bit / ký tự). Vì vậy, với Base64 có nhiều thông tin hơn được lưu trữ trong mỗi ký tự được mã hóa, tức là, 6 bit thông tin thay vì 3,32 bit.
TinyURL không băm bất cứ thứ gì, nó sử dụng số nguyên Cơ sở 36 (hoặc thậm chí là cơ số 62, sử dụng chữ thường và chữ hoa) để cho biết bản ghi nào sẽ truy cập.
Cơ số 36 đến Số nguyên:
intval($str, 36);
Số nguyên đến Cơ số 36:
base_convert($val, 10, 36);
Vì vậy, thay vì chuyển hướng đến một tuyến đường như /url/1234
nó đã trở thành /url/ax
thay vào đó. Điều này mang lại cho bạn nhiều công dụng hơn so với hash will, vì sẽ không có va chạm. Với điều này, bạn có thể dễ dàng kiểm tra xem url có tồn tại hay không và trả về ID thích hợp, hiện có trong cơ sở 36 mà người dùng không biết rằng nó đã có trong cơ sở dữ liệu.
Đừng băm, hãy sử dụng các cơ sở khác cho loại điều này. (Nó nhanh hơn và có thể chống va chạm.)
intval()
biến mọi thứ thành một con số. Tôi đoán có thể tôi đang nhầm lẫn về cách intval()
kết nối với các bước khác cần thiết để thực hiện chuyển hướng như vai trò của cơ sở dữ liệu.
intval()
là nếu của bạn $str
có dấu gạch chéo (/) hoặc dấu gạch ngang (-) trong đó. Tôi nhận ra điều đó on/stuff
, on-stuff
và on
tất cả đều trả lại số 887
. Bạn có giải pháp nào để làm việc với các URL có dấu gạch chéo và dấu gạch ngang trong đó không?
Tôi đã viết một lib nhỏ để tạo các băm bị xáo trộn từ các số nguyên.
http://web.archive.org/web/20130727034425/http://blog.kevburnsjr.com/php-unique-hash
$ids = range(1,10);
foreach($ids as $id) {
echo PseudoCrypt::unhash($id) . "\n";
}
m8z2p 8hy5e uqx83 gzwas 38vdh phug6 bqtiv xzslk k8ro9 6hqqy
14/7/2015: Thêm mã thực bên dưới, vì nó trở nên khó tìm:
<?php
/**
* PseudoCrypt by KevBurns (http://blog.kevburnsjr.com/php-unique-hash)
* Reference/source: http://stackoverflow.com/a/1464155/933782
*
* I want a short alphanumeric hash that’s unique and who’s sequence is difficult to deduce.
* I could run it out to md5 and trim the first n chars but that’s not going to be very unique.
* Storing a truncated checksum in a unique field means that the frequency of collisions will increase
* geometrically as the number of unique keys for a base 62 encoded integer approaches 62^n.
* I’d rather do it right than code myself a timebomb. So I came up with this.
*
* Sample Code:
*
* echo "<pre>";
* foreach(range(1, 10) as $n) {
* echo $n." - ";
* $hash = PseudoCrypt::hash($n, 6);
* echo $hash." - ";
* echo PseudoCrypt::unhash($hash)."<br/>";
* }
*
* Sample Results:
* 1 - cJinsP - 1
* 2 - EdRbko - 2
* 3 - qxAPdD - 3
* 4 - TGtDVc - 4
* 5 - 5ac1O1 - 5
* 6 - huKpGQ - 6
* 7 - KE3d8p - 7
* 8 - wXmR1E - 8
* 9 - YrVEtd - 9
* 10 - BBE2m2 - 10
*/
class PseudoCrypt {
/* Key: Next prime greater than 62 ^ n / 1.618033988749894848 */
/* Value: modular multiplicative inverse */
private static $golden_primes = array(
'1' => '1',
'41' => '59',
'2377' => '1677',
'147299' => '187507',
'9132313' => '5952585',
'566201239' => '643566407',
'35104476161' => '22071637057',
'2176477521929' => '294289236153',
'134941606358731' => '88879354792675',
'8366379594239857' => '7275288500431249',
'518715534842869223' => '280042546585394647'
);
/* Ascii : 0 9, A Z, a z */
/* $chars = array_merge(range(48,57), range(65,90), range(97,122)) */
private static $chars62 = array(
0=>48,1=>49,2=>50,3=>51,4=>52,5=>53,6=>54,7=>55,8=>56,9=>57,10=>65,
11=>66,12=>67,13=>68,14=>69,15=>70,16=>71,17=>72,18=>73,19=>74,20=>75,
21=>76,22=>77,23=>78,24=>79,25=>80,26=>81,27=>82,28=>83,29=>84,30=>85,
31=>86,32=>87,33=>88,34=>89,35=>90,36=>97,37=>98,38=>99,39=>100,40=>101,
41=>102,42=>103,43=>104,44=>105,45=>106,46=>107,47=>108,48=>109,49=>110,
50=>111,51=>112,52=>113,53=>114,54=>115,55=>116,56=>117,57=>118,58=>119,
59=>120,60=>121,61=>122
);
public static function base62($int) {
$key = "";
while(bccomp($int, 0) > 0) {
$mod = bcmod($int, 62);
$key .= chr(self::$chars62[$mod]);
$int = bcdiv($int, 62);
}
return strrev($key);
}
public static function hash($num, $len = 5) {
$ceil = bcpow(62, $len);
$primes = array_keys(self::$golden_primes);
$prime = $primes[$len];
$dec = bcmod(bcmul($num, $prime), $ceil);
$hash = self::base62($dec);
return str_pad($hash, $len, "0", STR_PAD_LEFT);
}
public static function unbase62($key) {
$int = 0;
foreach(str_split(strrev($key)) as $i => $char) {
$dec = array_search(ord($char), self::$chars62);
$int = bcadd(bcmul($dec, bcpow(62, $i)), $int);
}
return $int;
}
public static function unhash($hash) {
$len = strlen($hash);
$ceil = bcpow(62, $len);
$mmiprimes = array_values(self::$golden_primes);
$mmi = $mmiprimes[$len];
$num = self::unbase62($hash);
$dec = bcmod(bcmul($num, $mmi), $ceil);
return $dec;
}
}
Hàm băm ngắn nhất có độ dài 32 ký tự, bao giờ bạn có thể sử dụng 8 ký tự đầu tiên của mã băm md5
echo substr(md5('http://www.google.com'), 0, 8);
Cập nhật : đây là một lớp khác được tìm thấy ở đây được viết bởi Travell Perkins mà mất con số kỷ lục và tạo ra băm viết tắt của nó. 14 chữ số tạo ra chuỗi 8 chữ số. Đến ngày bạn đạt đến con số này, bạn trở nên nổi tiếng hơn tinyurl;)
class BaseIntEncoder {
//const $codeset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
//readable character set excluded (0,O,1,l)
const codeset = "23456789abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ";
static function encode($n){
$base = strlen(self::codeset);
$converted = '';
while ($n > 0) {
$converted = substr(self::codeset, bcmod($n,$base), 1) . $converted;
$n = self::bcFloor(bcdiv($n, $base));
}
return $converted ;
}
static function decode($code){
$base = strlen(self::codeset);
$c = '0';
for ($i = strlen($code); $i; $i--) {
$c = bcadd($c,bcmul(strpos(self::codeset, substr($code, (-1 * ( $i - strlen($code) )),1))
,bcpow($base,$i-1)));
}
return bcmul($c, 1, 0);
}
static private function bcFloor($x)
{
return bcmul($x, '1', 0);
}
static private function bcCeil($x)
{
$floor = bcFloor($x);
return bcadd($floor, ceil(bcsub($x, $floor)));
}
static private function bcRound($x)
{
$floor = bcFloor($x);
return bcadd($floor, round(bcsub($x, $floor)));
}
}
đây là ví dụ về cách sử dụng nó:
BaseIntEncoder::encode('1122344523');//result:3IcjVE
BaseIntEncoder::decode('3IcjVE');//result:1122344523
const codeset
có thể trong bất kỳ thứ tự tùy ý, chỉ để xáo trộn ++
Đối với một mã băm ngắn , thân thiện với url , trong quan điểm không cho phép nội dung trùng lặp có thể xảy ra, chúng tôi có thể sử dụng hash()
và đặc biệt là loại băm CRC , vì nó được tạo chính xác cho điều đó:
Kiểm tra dự phòng theo chu kỳ
Kiểm tra dự phòng theo chu kỳ (CRC) là một mã phát hiện lỗi thường được sử dụng trong các mạng kỹ thuật số và thiết bị lưu trữ để phát hiện những thay đổi ngẫu nhiên đối với dữ liệu thô. Các khối dữ liệu đi vào các hệ thống này được đính kèm một giá trị kiểm tra ngắn, dựa trên phần còn lại của một phép chia đa thức cho nội dung của chúng. Khi truy xuất, phép tính được lặp lại và trong trường hợp các giá trị kiểm tra không khớp, có thể thực hiện hành động khắc phục
echo hash("crc32", "Content of article...");
// Output fd3e7c6e
Câu trả lời hay nhất chưa từng có: Chuỗi "Hash Like" nhỏ nhất duy nhất được cung cấp ID cơ sở dữ liệu duy nhất - Giải pháp PHP, Không cần thư viện bên thứ ba.
Đây là mã:
<?php
/*
THE FOLLOWING CODE WILL PRINT:
A database_id value of 200 maps to 5K
A database_id value of 1 maps to 1
A database_id value of 1987645 maps to 16LOD
*/
$database_id = 200;
$base36value = dec2string($database_id, 36);
echo "A database_id value of $database_id maps to $base36value\n";
$database_id = 1;
$base36value = dec2string($database_id, 36);
echo "A database_id value of $database_id maps to $base36value\n";
$database_id = 1987645;
$base36value = dec2string($database_id, 36);
echo "A database_id value of $database_id maps to $base36value\n";
// HERE'S THE FUNCTION THAT DOES THE HEAVY LIFTING...
function dec2string ($decimal, $base)
// convert a decimal number into a string using $base
{
//DebugBreak();
global $error;
$string = null;
$base = (int)$base;
if ($base < 2 | $base > 36 | $base == 10) {
echo 'BASE must be in the range 2-9 or 11-36';
exit;
} // if
// maximum character string is 36 characters
$charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// strip off excess characters (anything beyond $base)
$charset = substr($charset, 0, $base);
if (!ereg('(^[0-9]{1,50}$)', trim($decimal))) {
$error['dec_input'] = 'Value must be a positive integer with < 50 digits';
return false;
} // if
do {
// get remainder after dividing by BASE
$remainder = bcmod($decimal, $base);
$char = substr($charset, $remainder, 1); // get CHAR from array
$string = "$char$string"; // prepend to output
//$decimal = ($decimal - $remainder) / $base;
$decimal = bcdiv(bcsub($decimal, $remainder), $base);
} while ($decimal > 0);
return $string;
}
?>
Trên thực tế, giải pháp tốt nhất để có băm "ngẫu nhiên" là tạo danh sách băm ngẫu nhiên, đặt nó trên Mysql với một INDEX duy nhất (bạn có thể viết một UDF đơn giản để chèn 100 000 hàng trong 1 giây).
Tôi nghĩ cấu trúc như thế này là ID | HASH | STATUS | URL | VIEWS | ......
Trạng thái ở đâu cho biết Hash này là miễn phí hay không.
Cách dễ dàng với kiểm tra trùng lặp trong Cơ sở dữ liệu:
$unique = false;
// While will be repeated until we get unique hash
while($unique == false) {
// Getting full hash based on random numbers
$full_hash = base64_encode( rand(9999,999999) );
// Taking only first 8 symbols
$hash = substr($full_hash, 0, 8);
// Checking for duplicate in Database - Laravel SQL syntax
$duplicate = \App\Item::where('url', $hash)->count();
// If no Duplicate, setting Hash as unique
if ($duplicate==0) {
// For stoping while
$unique=true;
// New Hash is confirmed as unique
$input['url']=$hash;
}
}
Tôi đang tạo một công cụ rút gọn url. Trong trường hợp của tôi, tôi đã sử dụng "id" của cơ sở dữ liệu để tạo mỗi lần một url ngắn duy nhất.
Những gì tôi đã làm là, đầu tiên -
Chèn Dữ liệu như "Url gốc" và "ngày tạo" trong db để trống "url ngắn" trong db. Sau đó lấy "id" từ đó và chuyển vào hàm bên dưới.
<?php
function genUniqueCode($id){
$id = $id + 100000000000;
return base_convert($id, 10, 36);
}
//Get Unique Code using ID
/*
id Below is retrived from Database after Inserting Original URL.
*/
$data['id'] =10;
$uniqueCode = genUniqueCode($data['id']);
// Generating the URL
$protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'?'https':'http';
echo "<a href='{$protocol}://{$_SERVER['HTTP_HOST']}/{$uniqueCode}'>{$protocol}://{$_SERVER['HTTP_HOST']}/{$uniqueCode}</a>";
?>
Và sau đó CẬP NHẬT giá trị của Mã url ngắn trong Cơ sở dữ liệu.
Ở đây tôi đang sử dụng "id" để tạo mã ngắn. Vì ID không thể giống nhau cho nhiều mục nhập. Nó là duy nhất do đó Mã hoặc Url duy nhất sẽ là duy nhất.