Someone suggested that I use tr.im to create short urls when sending tweets to twitter from my other web site. I was a little annoyed that they will only allow 10 urls per hour. I didn’t feel like figuring out their API and then asking for higher limits. I said to myself. It’s probably just as easy to write my own. So I did.
First, I needed to store the URL with a key so I could resolve the url when someone clicks on my link. Here is the class that I created for that
class ShortUrl {
var $database;
function ShortUrl($database) {
$this->database = $database;
}
function next() {
$sequence = $this->database."/sequence";
touch($sequence);
$handle = fopen($sequence, "r+") or die("can't open sequence file");
$last = fgets($handle);
if(empty($last) && $last != "0") {
$last = chr(47);
}
$next = substr_replace($last, $this->nextASCII(substr($last, -1)), -1);
rewind($handle);
fwrite($handle, $next);
fclose($handle);
return $next;
}
// 48-57,65-90,97-122
function nextASCII($char) {
$ascii = ord($char);
if ($ascii < 48) {
return chr(48);
} else if ($ascii > 56 && $ascii < 65) {
return chr(65);
} else if ($ascii > 89 && $ascii < 97) {
return chr(97);
} else if ($ascii > 121) {
return chr(122).chr(48);
}
$ascii += 1;
return chr($ascii);
}
function createShorty($URL) {
$shorty = $this->next();
$path = $this->database ."/". substr($shorty, 0, 1) . ".db";
touch($path);
$fp = fopen($path, "a");
fwrite($fp, $shorty . ":" . $URL . PHP_EOL);
return $shorty;
}
function resolveShorty($shorty) {
$path = $this->database ."/". substr($shorty, 0, 1) . ".db";
touch($path);
$fp = fopen($path, "r");
while (!feof($fp)) {
$line = trim(fgets($fp));
if(strcmp($shorty, substr($line, 0, strpos($line, ":"))) == 0) {
$url = substr($line, strpos($line, ":") + 1);
}
}
fclose($fp);
return $url;
}
}
The $database parameter in the constructor is a subdirectory where the files will be stored. The two functions that will be called are createShorty() and resolveShorty(). createShorty() reads the value that it stored in the file “sequence” and increments it by one to be used as the key. Then it saves that value back into the file “sequence” and stores it in a .db file along with the URL that is passed in. The generated key is passed back to the calling program to be used in the short url. I will talk about resolveShorty() later.
The key is used to create a short url here:
$shortObj = new ShortUrl("urldb");
$shorty = $shortObj->createShorty($item->link);
$shortUrl = "http://".$_SERVER["HTTP_HOST"]."/.$shorty";
The resulting URL looks something like this: http://www.zeptoworld.com/.0A. The key for the URL is “0A”. The “.” in front of it is what your code will use to recognize this as a short URL that needs to be resolved.
You will need to put something like this in your .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . redirect.php [L]
This tells the apache server that if it sees a URL that starts with a “.” then run the code in redirect.php. Here is what redirect.php looks like:
$uri = $_SERVER['REQUEST_URI'];
$shorty = substr($uri, 2);
$shortObj = new ShortUrl("urldb");
$url = $shortObj->resolveShorty($shorty);
header("http/1.1 307 temporary redirect");
header("Location: $url");
resolveShorty() will find the original URL that was stored in the file. Then you do a redirect to the intended page and you are done.