Ich suche nach einer PHP-Funktion, die aus einem String oder einer Datei einen kurzen Hash erstellt, ähnlich wie Websites mit URL-Verkürzung wie tinyurl.com
Der Hash sollte nicht länger als 8 Zeichen sein.
Ich suche nach einer PHP-Funktion, die aus einem String oder einer Datei einen kurzen Hash erstellt, ähnlich wie Websites mit URL-Verkürzung wie tinyurl.com
Der Hash sollte nicht länger als 8 Zeichen sein.
Alphabet::convert($hash, Alphabet::HEX, Alphabet::ALPHANUMERIC)
können Sie MD5 auf 22 (von 32) Zeichen reduzieren. Sie möchten stattdessen die Ganzzahl-IDs der Dateien (z. B. aus Ihrer Datenbank) mit codieren(new Id())->encode($id)
.Antworten:
URL-Verkürzungsdienste verwenden eher einen automatisch inkrementierten ganzzahligen Wert (wie eine zusätzliche Datenbank-ID) und codieren diesen mit Base64 oder anderen Codierungen, um mehr Informationen pro Zeichen zu erhalten (64 statt nur 10 wie Ziffern).
quelle
0
-9
eine Zahl darzustellen, Sie haben 10 mögliche Werte pro codierten Zeichen (ld (10) ≈ 3,32 Bits / Zeichen). Wenn Sie jedoch dieselbe Zahl mit Base64-Zeichen darstellen, haben Sie 64 mögliche Werte pro codiertem Zeichen (ld (64) = 6 Bit / Zeichen). Bei Base64 sind also mehr Informationen in jedem codierten Zeichen gespeichert, dh 6 Informationsbits anstelle von 3,32 Bit.TinyURL hasht nichts, sondern verwendet Ganzzahlen der Basis 36 (oder sogar Basis 62 mit Klein- und Großbuchstaben), um anzugeben, welcher Datensatz besucht werden soll.
Basis 36 bis Ganzzahl:
intval($str, 36);
Ganzzahl zur Basis 36:
base_convert($val, 10, 36);
Also, anstatt zu einer Route umzuleiten, wie
/url/1234
es/url/ax
stattdessen wird. Dies gibt Ihnen viel mehr Nutzen als ein Hash, da es keine Kollisionen gibt. Auf diese Weise können Sie leicht überprüfen, ob eine URL vorhanden ist, und die richtige, vorhandene ID in Basis 36 zurückgeben, ohne dass der Benutzer weiß, dass sie bereits in der Datenbank vorhanden ist.Hasch nicht, benutze andere Basen für solche Dinge. (Es ist schneller und kann kollisionssicher gemacht werden.)
quelle
intval()
verwandelt aber alles in eine Zahl. Ich bin vielleicht verwirrt darüber, wie dieintval()
Verbindung zu den anderen Schritten hergestellt wird, die für die Umleitung erforderlich sind, wie z. B. die Rolle der Datenbank.intval()
ist, wenn$str
es Schrägstriche (/) oder Bindestriche (-) enthält. Ich erkannte , dasson/stuff
,on-stuff
und dieon
ganze Zahl zurückgegeben887
. Haben Sie eine Lösung für die Arbeit mit URLs mit Schrägstrichen und Bindestrichen?Ich habe eine winzige Bibliothek geschrieben, um verschleierte Hashes aus ganzen Zahlen zu generieren.
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"; }
14.07.2015: Hinzufügen des aktuellen Codes unten, da es schwierig geworden ist, Folgendes zu finden:
<?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; } }
quelle
Der kürzeste Hash hat eine Länge von 32 Zeichen. Sie können jedoch die ersten 8 Zeichen des MD5-Hash verwenden
echo substr(md5('http://www.google.com'), 0, 8);
Update : hier ist eine andere Klasse gefunden hier durch schriftliche Travell Perkins , die Rekordzahl nimmt und erstellen kurze Hash dafür. Die 14-stellige Nummer erzeugt eine 8-stellige Zeichenfolge. Ab dem Datum, an dem Sie diese Zahl erreichen, werden Sie beliebter als 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))); } }
Hier ist ein Beispiel für die Verwendung:
BaseIntEncoder::encode('1122344523');//result:3IcjVE BaseIntEncoder::decode('3IcjVE');//result:1122344523
quelle
const codeset
Für einen kurzen Hash , url freundlich , im Hinblick auf mögliche doppelte Inhalte nicht anzuerkennen, können wir verwenden ,
hash()
und vor allem des CRC - Hash - Typ, da es genau gemacht hat dafür:echo hash("crc32", "Content of article..."); // Output fd3e7c6e
quelle
Beste Antwort bisher: Kleinste eindeutige "Hash-ähnliche" Zeichenfolge bei eindeutiger Datenbank-ID - PHP-Lösung, keine Bibliotheken von Drittanbietern erforderlich.
Hier ist der Code:
<?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; } ?>
quelle
Die beste Lösung für "zufälligen" Hash besteht darin, eine Liste mit zufälligen Hashs zu erstellen und diese mit einem eindeutigen INDEX auf MySQL zu stellen (Sie können eine einfache UDF schreiben, um 100 000 Zeilen in 1 Sekunde einzufügen).
Ich denke eine Struktur wie diese ID | HASH | STATUS | URL | VIEWS | ......
Wobei der Status angibt, ob dieser Hash frei ist oder nicht.
quelle
Einfacher Weg mit doppelter Prüfung in der Datenbank:
$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; } }
quelle
Ich habe eine URL kürzer gemacht. In meinem Fall habe ich die "ID" der Datenbank verwendet, um jedes Mal eine eindeutige kurze URL zu erstellen.
Was ich getan habe ist, zuerst -
Fügen Sie Daten wie "Original-URL" und "Erstellungsdatum" in die Datenbank ein und lassen Sie die "kurze URL" in der Datenbank leer. Holen Sie sich dann die "ID" von dort und übergeben Sie die unten stehende Funktion.
<?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>"; ?>
Und dann UPDATE-Wert des Kurz-URL-Codes in der Datenbank.
Hier verwende ich "id", um einen Kurzcode zu erstellen. Da ID für Mehrfacheinträge nicht identisch sein kann. Es ist einzigartig, daher ist der eindeutige Code oder die eindeutige URL eindeutig.
quelle