मैं एक PHP फ़ंक्शन की तलाश कर रहा हूं, जो एक छोटे से स्ट्रिंग या फ़ाइल से हैश करता है, जैसे कि URL- कम करने वाली वेबसाइट्स जैसे smallll.com।
हैश 8 अक्षरों से अधिक लंबा नहीं होना चाहिए।
मैं एक PHP फ़ंक्शन की तलाश कर रहा हूं, जो एक छोटे से स्ट्रिंग या फ़ाइल से हैश करता है, जैसे कि URL- कम करने वाली वेबसाइट्स जैसे smallll.com।
हैश 8 अक्षरों से अधिक लंबा नहीं होना चाहिए।
Alphabet::convert($hash, Alphabet::HEX, Alphabet::ALPHANUMERIC)
, आप एमडी 5 को 22 से नीचे (32 से) वर्ण प्राप्त कर सकते हैं। इसके बजाय आप जो चाहते हैं, वह फाइलों के पूर्णांक आईडी (जैसे आपके डेटाबेस से) को कूटबद्ध करता है (new Id())->encode($id)
।
जवाबों:
URL छोटा करने वाली सेवाएं बल्कि एक ऑटो इंक्रीमेंट किए गए पूर्णांक मान (जैसे एक अनुपूरक डेटाबेस आईडी) का उपयोग करती हैं और यह मानती हैं कि बेस 64 या अन्य एन्कोडिंग के साथ प्रति वर्ण अधिक जानकारी है (64 अंकों के बजाय केवल 10 की तरह)।
0
- 9
एक संख्या का प्रतिनिधित्व करने के लिए, आपके पास एन्कोडेड वर्ण (ld (10) 10 3.32 बिट्स / वर्ण) प्रति 10 संभावित मान हैं। हालाँकि, यदि आप Base64 वर्णों के साथ समान संख्या का प्रतिनिधित्व करते हैं, तो आपके पास प्रति एन्कोडेड वर्ण (ld (64) = 6 बिट्स / वर्ण) प्रति 64 संभावित मान हैं। इसलिए Base64 के साथ प्रत्येक एन्कोडेड वर्ण में संग्रहीत अधिक जानकारी है, अर्थात, 3.32 बिट्स के बजाय 6 बिट्स की जानकारी।
TinyURL के पास कुछ भी नहीं है, यह देखने के लिए कि कौन सा रिकॉर्ड देखने के लिए बेस 36 पूर्णांक (या निम्न 62, निचले और बड़े अक्षरों का उपयोग करके) का उपयोग करता है।
बेस 36 इंटेगर को:
intval($str, 36);
बेस 36 के लिए पूर्णांक:
base_convert($val, 10, 36);
तो फिर, इसके बजाय एक मार्ग पर पुनर्निर्देशित करने के बजाय /url/1234
ऐसा हो जाता है /url/ax
। यह आपको एक हैश की तुलना में पूरे बहुत अधिक उपयोग देता है, क्योंकि कोई टकराव नहीं होगा। इसके साथ आप आसानी से जांच कर सकते हैं कि कोई url मौजूद है या नहीं, उपयोगकर्ता में आधार 36 में उचित, मौजूदा, ID को यह जाने बिना कि यह डेटाबेस में पहले से था।
हैश मत करो, इस तरह की चीज के लिए अन्य अड्डों का उपयोग करें। (यह तेज़ है और इसे टक्कर-प्रूफ बनाया जा सकता है।)
intval()
सब कुछ एक संख्या में बदल देता है। मुझे लगता है कि शायद मैं भ्रमित हूं intval()
कि डेटाबेस की भूमिका की तरह पुनर्निर्देशित करने के लिए आवश्यक अन्य चरणों से कैसे जुड़ता है।
intval()
, अगर इसमें आपके $str
पास स्लैश (/) या डैश (-) है। मुझे एहसास हुआ कि on/stuff
, on-stuff
और on
सभी ने नंबर वापस कर दिया 887
। क्या आपके पास URL के साथ स्लैश और डैश में काम करने के लिए एक समाधान है?
मैंने पूर्णांक से obfuscated hashes उत्पन्न करने के लिए एक छोटा सा lib लिखा।
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
7/14/2015: नीचे वास्तविक कोड जोड़ना, क्योंकि इसे ढूंढना मुश्किल हो गया है:
<?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;
}
}
सबसे छोटा हैश 32 वर्ण की लंबाई है, कभी भी आप md5 हैश के पहले 8 अक्षरों का उपयोग कर सकते हैं
echo substr(md5('http://www.google.com'), 0, 8);
अपडेट करें : यहां एक और वर्ग पाया गया है जिसे ट्रेवेल पर्किन्स द्वारा लिखा गया है जो रिकॉर्ड संख्या लेता है और इसके लिए शॉर्ट हैश बनाता है। 14 अंकों की संख्या 8 अंक स्ट्रिंग का उत्पादन करती है। जिस तारीख तक आप इस संख्या तक पहुँचते हैं, आप टिनीर्ल की तुलना में अधिक लोकप्रिय हो जाते हैं;)
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)));
}
}
यहाँ उदाहरण है कि इसका उपयोग कैसे किया जाए:
BaseIntEncoder::encode('1122344523');//result:3IcjVE
BaseIntEncoder::decode('3IcjVE');//result:1122344523
const codeset
किसी भी मनमाने ढंग से आदेश हो सकता है, बस ++ को
एक छोटी हैश के लिए , यूआरएल के अनुकूल , संभव डुप्लिकेट सामग्री को रोकने के मद्देनजर, हम उपयोग कर सकते हैं hash()
और विशेष रूप से सीआरसी हैश प्रकार, क्योंकि यह इसके लिए बिल्कुल बनाया गया है:
चक्रीय अतिरेक की जाँच
एक चक्रीय अतिरेक जांच (CRC) एक त्रुटि-पता लगाने वाला कोड है जो आमतौर पर डिजिटल नेटवर्क और भंडारण उपकरणों में उपयोग किया जाता है ताकि कच्चे डेटा के आकस्मिक परिवर्तनों का पता लगाया जा सके। इन प्रणालियों में प्रवेश करने वाले डेटा के ब्लॉक उनकी सामग्री के एक बहुपद विभाजन के शेष के आधार पर, एक छोटा चेक वैल्यू संलग्न करते हैं। पुनर्प्राप्ति पर, गणना को दोहराया जाता है और, घटना में चेक मान मेल नहीं खाते हैं, सुधारात्मक कार्रवाई की जा सकती है
echo hash("crc32", "Content of article...");
// Output fd3e7c6e
सर्वश्रेष्ठ उत्तर अभी तक: सबसे छोटा अनोखा "हैश लाइक" स्ट्रिंग को देखते हुए यूनिक डेटाबेस आईडी - पीएचपी सॉल्यूशन, कोई थर्ड पार्टी लाइब्रेरी आवश्यक नहीं है।
यहाँ कोड है:
<?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;
}
?>
वास्तव में "यादृच्छिक" हैश का सबसे अच्छा समाधान यादृच्छिक हैश की एक सूची उत्पन्न करना है, इसे एक अद्वितीय INDEX के साथ मैसकल पर रख दें (आप 1 सेकंड में 100 000 पंक्तियों को सम्मिलित करने के लिए एक सरल यूडीएफ लिख सकते हैं)।
मुझे लगता है कि इस आईडी जैसी संरचना | HASH | STATUS | URL | VIEWS |
जहां स्थिति इंगित करती है कि यह हैश मुक्त है या नहीं।
डेटाबेस में डुप्लिकेट जाँच के साथ आसान तरीका:
$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;
}
}
मैं एक url शॉर्टनर बना रहा था। मेरे मामले में मैंने हर बार एक यूनिक शॉर्ट यूआरएल बनाने के लिए डेटाबेस की "आईडी" का उपयोग किया।
मैंने जो किया, वह पहला -
Db में "शॉर्ट url" को खाली छोड़ने के लिए db में "ओरिजिनल यूआरएल" और "क्रिएशन डेट" जैसे डेटा डालें। फिर वहां से "आईडी" प्राप्त करें और नीचे फ़ंक्शन में पास करें।
<?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>";
?>
और फिर डेटाबेस में शॉर्ट यूआरएल कोड का अद्यतन मूल्य।
यहाँ मैं शॉर्ट कोड बनाने के लिए "id" का उपयोग कर रहा हूँ। चूंकि बहु प्रविष्टियों के लिए आईडी समान नहीं हो सकती है। यह अद्वितीय है इसलिए यूनिक कोड या यूआरएल अद्वितीय होगा।