PHP: Create your own url shortener with this easy to use PHP Class
After using Twitter some time now, i saw several URL shortening services and a few scripts that would do the work. But i did not see any PHP Class for doing this job easily. So i wrote one myself ...
The most mentioned code example for this application floating around on Twitter is this one written by jaisen. Its a good start but had some things i would do different.
Goals
Let me start with what i wanted to achieve:
- Write a simple to use PHP Class for saving, shortening and redirecting URLs.
- URLs should be stored in a MySQL database.
- Number of URLs should not be limited too early.
- No duplicate URL entry's in database.
- A simple hit counter for each URL.
- Short URL should be case-insensitive.
Source
Link to the source: http://juliusbeckmann.de/classes/src/url_shortener/url_shortener.zip
And direct source view: http://juliusbeckmann.de/classes/src/url_shortener/
Documentation
Here you can find the documentation: http://juliusbeckmann.de/classes/
Demo
A live demo of my class: http://juliusbeckmann.de/url_shortener/
Process of developing
Some people think that a URL shortener somehow shortens a long URL like "http://google.com" to something like "b7ic3". There is no compression done, the URL will be stored in a database with the unique key "b7ic3". This is the whole magic.
Main problem of this concept, how do we generate the key "b7ic3"? I saw some functions that can do that but i decided to use the PHP build in function base_convert(). I use this function to convert a number like 1234 to its base 36 (a..z and 0..9) equivalent "ya". One downside of this function is, that only lowercase chars will be generated which will result in a lower "compress ratio". But this is wanted because some programs like the original ICQ Chat client sometimes handles case-sensitive URLs incorrect. It is also easier to spell case-insensitive URL on the phone.
The principle with the short URL key works like this:
We insert a new URL to our database and use mysql_insert_id() to get the next id given away from AUTO INCREMENT. This decimal number will be converted to the equivalent base 36 one, and viola - we have our unique key. I know this method is not the best if old URLs get deleted, but it will work always and there will be no duplicate keys.
I build in a special security feature that is often forgotten or even unknown.
This is important. If an attacker would be able to inject newlines to our url, he could change the "Location: "-Header and create a second request answer.
Options
If you want to use a different base, just configure this parameter:
Possible values are from 2 up to 36.
I also build in a URL validation. This is to prevent that URLs other than http or https are shortened. To change this validation configure this parameter:
If you want to define bad words or even whole URLs, use this parameter. Each URL that contains a word from this list will not be shortened:
Methods
The whole class has only 5 public methods.
This function creates a new short URL. If the URL is already in the database no new entry will be made. This function will return a array with all relevant data inside, or an empty array on error.
This function will give you the data for a specific key. The return is the same data like new_redirect().
If you want to log redirect hits, just call this method and the hit counter for this key will be +1.
If you want to know how much hits a key already got, use this method.
Simply returns the number of URLs in our database.
Table structure
Here is the table structure my class uses:
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`md5` char(32) NOT NULL,
`ts` int(10) UNSIGNED NOT NULL,
`ip` int(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
KEY `md5` (`md5`)
) ENGINE=MyISAM AUTO_INCREMENT=1000 ;
The id column will be used to identify a URL. The principle is easy. If the key is "ya", the URL with the id 123 is asked. There is also a md5 column in which the md5 of the URL will be stored. This is done for faster searching on duplicate URLs and to validate if a URL is still correct.
Some additional data like timestamp and ip are also stored. ip is stored in a shorter format.
If you want to log the number of hits, this is the used table structure:
`id` BIGINT UNSIGNED NOT NULL ,
`hits` BIGINT UNSIGNED NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE = MYISAM;
It is important to say that we need a second table for this because otherwise we would write instantly to the table MySQL needs to read from. This would lead to serious performance troubles.
I inserted about 100.000 URLs, each with at least one hit. The whole database needed about 17MB of space, which are ~180 Byte per URL. This is a good value if you think how much information is saved.
Last Words
Es you can see, the class has all functions needed for a simple and secure URL shortener. You can find a short example index.php with htaccess in the source dir. If you find mistakes or errors, please write a comment.
No related posts.
Thank for all, your class is the only one fully documented and ready to use. I use it, and i talk of you on my blog ;-)
Hello, i have a question
i want too have an url like : short.mywebsite.com
the folder of the sub domaine is mywebsite.com/short
i can't make the htaccess work. Can you help me ?
Thank for all
Philippe
You need a "VHost" for your Webserver and a A-DNS-Record for your Domain to get "short.mywebsite.com" working.
there XSS vulnerability in your code...
try with this;
Do you have a full example, please?