URL shortening services rather use a auto incremented integer value (like a supplementary database ID) and encode that with Base64 or other encodings to have more information per character (64 instead of just 10 like digits).
Shortest hash is 32 character length, how ever you can use first 8 characters of md5 hash
echo substr(md5('http://www.google.com'), 0, 8);
Update: here is another class found here written by Travell Perkins which takes record number and create short hash for it. 14 digits number produce 8 digit string. By the date you reach this number you become more popular than tinyurl ;)
TinyURL doesn't hash anything, it uses Base 36 integers (or even base 62, using lower and uppercase letters) to indicate which record to visit.
Base 36 to Integer:
intval($str, 36);
Integer to Base 36:
base_convert($val, 10, 36);
So then, instead of redirecting to a route like /url/1234 it becomes /url/ax instead. This gives you a whole lot more use than a hash will, as there will be no collisions. With this you can easily check if a url exists and return the proper, existing, ID in base 36 without the user knowing that it was already in the database.
Don't hash, use other bases for this kind of thing. (It's faster and can be made collision-proof.)
Actually the best solution to have "random" hash is to generate a list of random hash, put it on Mysql with an unique INDEX (you can write a simple UDF to insert 100 000 rows in 1 seconde).
I think a structure like this ID|HASH|STATUS|URL|VIEWS|......
Where status indicates if this Hash is free or not.
<?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;
}
?>
I was making a url shortner. In my case I used the "id" of database to create every time a unique short url.
What I did is, first -
Insert Data like "Original url" and "creation date" in db leaving the "short url" empty in db.
Then get the "id" from there and pass in the function below.
<?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>";
?>
And then UPDATE value of Short Url Code in Database.
Here I'm using "id" to create short code. Since ID can't be same for multi entries. It's unique hence the Unique Code or Url will be unique.
For a short hash, url friendly, in the view of disallowing possible duplicate contents, we can use hash() and especially the CRC or Adler-32 type, since they are made exactly for that:
Cyclic Redundancy Check
A cyclic redundancy check (CRC) is an error-detecting code commonly
used in digital networks and storage devices to detect accidental
changes to raw data. Blocks of data entering these systems get a short
check value attached, based on the remainder of a polynomial division
of their contents. On retrieval, the calculation is repeated and, in
the event the check values do not match, corrective action can be
taken
https://en.wikipedia.org/wiki/Cyclic_redundancy_check
Adler-32 is a checksum algorithm (...), compared to a
Cyclic Redundancy Check of the same length, it trades reliability for
speed (preferring the latter)
https://en.wikipedia.org/wiki/Adler-32
echo hash("crc32", "Content of article...");
// Output fd3e7c6e
echo hash("adler32", "Content of article...");
// Output 55df075f
uses only symbols you allow (so it can be case sensitive easily)
also unique
case insensitive from a box
only for positive int (for IDs)
<?php
class PseudoCrypt1
{
private static $keychars = 'CZPXD5H2FIWB81KE76JY93V4ORLAMT0QSUNG'; // Dictionary of allowed unique symbols, shuffle it for yourself or remove unwanted chars (don't forget to call testParameters after changing)
private static $divider = 19; // Tune divider for yourself (don't forget to call testParameters after changing)
private static $biasDivider = 14; // Tune bias divider for yourself (don't forget to call testParameters after changing)
private static $noise = 53; // Any positive number
public static function testParameters()
{
if (strlen(static::$keychars) < static::$divider + static::$biasDivider - 1) {
throw new Exception('Check your divider and biasDivider. It must be less than keychars length');
}
}
public static function encode(int $i): string
{
if ($i < 0) {
throw new Exception('Expected positive integer');
}
$keychars = static::$keychars;
$i = $i + static::$noise; // add noise to a number
$bias = $i % static::$biasDivider;
$res = '';
while ($i > 0) {
$div = $i % static::$divider;
$i = intdiv($i, static::$divider);
$res .= $keychars[$div + $bias];
}
// Current version of an algorithm is one of these chars (if in the future you will need to identify a version)
// Remember this chars on migrating to a new algorithm/parameters
$res .= str_shuffle('LPTKEZG')[0];
$res .= $keychars[$bias]; // Encoded bias
return $res;
}
public static function decode($code)
{
$keychars = static::$keychars;
$biasC = substr($code, -1);
$bias = strpos($keychars, $biasC);
$code = substr($code, 0, -2);
$code = str_split(strrev($code));
$val = 0;
foreach ($code as $c) {
$val *= static::$divider;
$val += strpos($keychars, $c) - $bias;
}
return $val - static::$noise;
}
}