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).
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.)
intval()
verwandelt aber alles in eine Zahl. Ich bin vielleicht verwirrt darüber, wie die intval()
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 , dass on/stuff
, on-stuff
und die on
ganze Zahl zurückgegeben 887
. 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";
}
m8z2p 8hy5e uqx83 gzwas 38vdh phug6 bqtiv xzslk k8ro9 6hqqy
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;
}
}
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
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:
Zyklische Redundanzprüfung
Eine zyklische Redundanzprüfung (CRC) ist ein Fehlererkennungscode, der üblicherweise in digitalen Netzwerken und Speichergeräten verwendet wird, um versehentliche Änderungen an Rohdaten zu erkennen. Datenblöcke, die in diese Systeme eingegeben werden, erhalten einen kurzen Prüfwert, der auf dem Rest einer Polynomaufteilung ihres Inhalts basiert. Beim Abrufen wird die Berechnung wiederholt, und falls die Prüfwerte nicht übereinstimmen, können Korrekturmaßnahmen ergriffen werden
echo hash("crc32", "Content of article...");
// Output fd3e7c6e
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;
}
?>
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.
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;
}
}
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.