08.09
Hello all,
First let’s explain the basics of what we are trying to do.
We’ll build a script that will replace any type of url to a tiny url so it’s easier to post or be untraceable.
For example this *long* google maps url
http://maps.google.fr/maps?f=q&source=s_q&hl=fr&geocode=&q=white+house&sll=46.75984,1.738281&sspn=10.178118,28.54248&ie=UTF8&z=15&iwloc=A
could become
http://your.site/v/12345
you can check it out here : http://www.djpate.com/portfolio/shortURL/create.php
and download the source code here
This is not very hard to do but it’s nice tutorial for beginners.
Ok so let’s start with the DB schema.
CREATE TABLE `urls` ( `id` INT NOT NULL , `url` VARCHAR( 250 ) NOT NULL , `expire` DATETIME NOT NULL , PRIMARY KEY ( `id` ) ) ENGINE = MYISAM ;
id will be our identification hash, we won’t use auto increment for privacy purpose.
We dont want a bot to check all link starting from 1.
url is the actual url that will be redirecting to
and expire is the time when to delete the record from our db. I’ll take more about this feature later.
Now that you have your db setup let’s create the db connection page. It’s always good to have only one file doing all the db stuff.
mysql.php
<?php
mysql_connect("yourHost","yourLogin","yourPass") or die(mysql_error()); //connects to the db
mysql_select_db("yourDb") or die(mysql_error()); // selects the right db
?>
now the creation page.
create.php
<?php
require("mysql.php"); // to establish a connection to the db
/* configurations options */
$lengthOfTheHash = 5; // the length determine the numbers of chars in the hash created 5 => 12345 for example
$timeToExpire = 1; // in days
$urlOfYourSite = "http://www.djpate.com/portfolio/shortURL";
function createHash($length=5){ // very simple hash function to generate a random string
$valid = 0;
while(!$valid){
for($i=0;$i<$length;$i++){
$possibleValues = "123456789"; // if you want to add letters you will have to change the id to varchar instead of int
// pick a random character from the possible ones
$hash .= substr($possibleValues, mt_rand(0, strlen($possibleValues)-1), 1);
}
$check = mysql_query("select id from urls where id = $hash") or die(mysql_error()); // checks if the hash allready exists in the db , not very likely to happen
if(mysql_num_rows($check)==0){
$valid = 1;
}
}
return $hash;
}
if(isset($_POST['url'])){ // post was posted
//here we want to validate that the url is valid with a regexp
if(preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i',$_POST['url'])){
$hash = createHash($lengthOfTheHash);
mysql_query("insert into urls (id,url,expire)
values ($hash,'".addslashes($_POST['url'])."',date_add(now(),interval $timeToExpire day))") or die(mysql_error());
echo "Congrats ! here is your link : <a href=\"$urlOfYourSite/v/$hash\">$urlOfYourSite/v/$hash</a>";
} else {
echo "Invalid url !";
}
} else {
// no post data so we display the form
?>
<form method="post">
URL : <input type=text name=url />
<input type=submit value=go />
</form>
<?php
}
?>
now let’s create the redirection page
show.php
<?php
if($_GET['id']){
require("mysql.php"); // to establish a connection to the db
$id = addslashes($_GET['id']);
$getUrl = mysql_query("select url from urls where id = $id"); // check if the id exists in the db
if(mysql_num_rows($getUrl)==1){ // if so we redirect using the header function
$url = mysql_fetch_array($getUrl);
header("location:".$url['url']);
} else {
echo "Error : invalid hash";
}
} else {
echo "Error : no hash";
}
?>
And to finish up let’s make a simple url rewrite so we dont have to see the show.php
.htaccess
Options +FollowSymlinks RewriteEngine on RewriteRule ^v/([0-9]*)$ show.php?id=$1 [L]
note : dont’ forget to check that you have enable the mod_rewrite on your apache conf !
Bonus
At this point everything should be working but you’ll end up having a problem with the url that stays in your db for years so you have to setup a cron to remove the url that reaches there expire date.
We could do a real cron but you would need to have ssh access and php-cli installed and probably if you know what i’m talking about you dont need my help to do that.
For those who can’t setup a real cron we are simply going to check to delete all the old record everytime someone create a new one.
so you can just add this line before $hash = createHash($lengthOfTheHash); in create.php
mysql_query("delete from urls where expire < now()");
this will remove all url where expire date is inferior to the current date.
Enjoy and leave some comments if you liked this tutorial
Nice, sweet, and straight to the point.
It’s not working, IIS error says page could not found.
It’s not supposed to work on IIS.
The htaccess file to manage the url rewriting is based on apache2.
There is probably a equivalent for IIS but I don’t know much about it.
I suppose that if you google url rewrite IIS you should find what you need
Thank you for the reply.
How about someone starts to use the service for spamming? And you need to delete those urls… Do i like have to try do it in phpmyadmin or something?
Yes ATM you’ll have to delete those links thru phpMyAdmin or equivalent.
I’ll try to write a tutorial on how to create a simple CRUD(create update delete) system to do basic admin
Hi there, awesome script and easy to inlude within other pages. However, I get the “URL does not exist” a lot with certain domains and long ones like: hxxp://entrepreneurs.about.com/od/homebasedbusiness/a/makemoneyonline.htm – is there some thing I missed?
Edit: I meant “invalid url!” warning when I type anything in loner then 50 characters.
@Shaun
Thank you for pointing that out !
There was something wrong with my regexp so I found a better one on the net.
basicly you have to change line 28 in create.php
replace
if(ereg("^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$",$_POST['url'])){by
if(preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i',$_POST['url'])){I tested a few urls and the one of your comment and they all work fine now.
Sorry I missed it
This is pretty neat. I got it to work and have been experimenting with adding html to the pages. It\’s not difficult, but what I want to do is create a top frame and have the URL open in a bottom frame. I assume this is possible with the header function while keeping the redirect of the url, but I have no idea how
Is it easy? how do I go about doing it? I was thinking about using another page but I don\’t believe the url var will page too another php page. Thanks
basicly you just have to load show.php in the frame and pass the id using $_GET
<FRAME src=”show.php?id=XYZ”>
What would someone put if we didn’t want the URL to expire ever?
Basicly just don’t put that line
mysql_query(“delete from urls where expire < now()”);
and url will never expire.
Hi, Nice site
I’m not using database like mysql for my planning site but stored data in flat file (plain text) so i need my url shorter without touch mysql, may you have any solution?
now still work in localhost (127.0.0.1)
my existing url like:
http://localhost/games/play.php or
http://localhost/games/play.php/level/1/mountain/
I just want to hide the .php ext or change it to .htm\l
i.e. http://localhost/games/play/level/1/mountain/
I was try using .htacces
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ $1.php [R=301,nc]
when i call http://localhost/games/play.htm my url become
http://localhost/C:/xampp/htdocs/games/play.php (Error 403 , Access forbidden!)
but still work with http://localhost/games/play.php
help…
The problem you will face using a flat file is for the url key, you’ll have to parse line by line to find the right one.This can be very ressource hungry if you have more & more url to shorten.
Maybe if you really want to use a flat file you can use sqllite.It’s like mysql but is stored in a flat file.
As for you problem this is probably related to windows i guess but you can probably use a workaround such as
RewriteRule ^(.*)\.htm$ http://localhost/games/play/$1.php [R=301,nc]
I try to use this script with generating hash from numbers and letteers. Make change id to VARCHAR type and receive this error: Unknown column ‘uhQyqn3M5gUM5Bb’ in ‘field list’
With numbers only works great.
Could you tell me what is wrong?
its working good on my site http://www.adshow.eu/ads.php
you have to change
this
select url from urls where id = $id
to
select url from urls where id = ‘$id’
to make it work with varchar…
Nice code! I’ve one question though:
The script uses the following line:
echo “Congrats ! here is your link : $urlOfYourSite/v/$hash“;
and the following line in .htaccess file:
RewriteRule ^v/([0-9]*)$ show.php?id=$1 [L]
Now, I’d like to create URLs without the /v parts (for instance: http://www.mysite.com/12345 instead of http://www.mysite.com/v/12345). Why can’t I just to remove the /v parts form the codefiles and ^v part from the .htaccess file and what should I do in order to make it work?
Thanks!
Hello and thant you for your feeback.
you should be able to remove /v with no issue did you have some ?
removing all the /v parts form create.php and index.php and removing the ^v part from the .htaccess file results into a 404 error.
my create.php and index.php files now look like this:
echo “Congrats ! here is your link : $urlOfYourSite/$hash“;
-> so i only removed the /v parts.
my .htaccess file now looks like this:
Options +FollowSymlinks
RewriteEngine on
RewriteRule /([0-9]*)$ show.php?id=$1 [L]
-> so i only removed the ^v
you need to keep the ^ in the htaccess file.
RewriteRule ^([0-9]*)$ show.php?id=$1 [L] should work
^ means start of the reg ex
Hello, thanks for the Code, but I have also the same problem as Tommy:
I changed
select url from urls where id = $id
to
select url from urls where id = ‘$id’
and also I changed
INT
to VARCHAR
but there is also the error: Unknown column ‘pm4b’ in ‘field list’
Could you help me?
Best Regards
I copied the exact RewriteRule ^([0-9]*)$ show.php?id=$1 line into .htaccess files on two different servers. Both times, I got the “error: no hash” message (not the text box in order to shorten a link I expected). If I type http://www.mysite/12235 directly in the urlbar it works though. Any tips on how to get the shorten textbox when typing http://www.mysite.com and a redirect when typing (or clicking) http://www.mysite.com/12235?
Thanks in advance!
nice! this is exactly what i find!
Thank you for this nice script … works perfect!!!
How can i protect my shorter?
I don’t want to run it public… it’s only for me