PHP TutorialsWeb Developer

Create a Custom URL Shortener in PHP

Written by:

Learn how to create a custom URL shortener in PHP. This custom URL shortener will be super simple and can be created in about a hour or two if you are a decent coder. Our custom URL shortener will be coded using PHP, HTML, and jQuery. The PHP code will make the URL shortener work on the back end server. The full source code for our custom URL shortener are available at the link below.

Download the FREE SOURCE CODE for this tutorial: Download Source Code

The Setup: Let’s Break it Down

For starters, this custom URL shortener we are about to create will be a fully functional website with a super short domain, So at any point you want to view the final product you can go there to check it out.

Our URL shortener will only need a few different files and only about 400 lines of code, not including the jQuery library. The list of the file breakdown is below:

  • include.php – this will hold some the database connection information and some custom simple functions that we will reuse a few times.
  • index.php – the one and only page the user will ever see of our website. It will have the form the user will submit and where their custom generated shortened url will be displayed for them.
  • process.php – this file will handle the back-end database processing for the form. Having this code in a separate file is crucial for sing jQuery and javascript to submit the form.
  • .htaccess – this file will allow us to have our custom coded urls (e.g., so we can use random unique codes to redirect to the appropriate URLs.
  • main.css – the primary stylesheet for the site, just enough to make it look at least a little pretty.
  • jquery.js – the jQuery library will allow us to submit our form using javascript. If you want to learn more about jQuery, look at official jQuery documentation site, it is jam packed with useful info.

Create the database table structure

For this url shortener, we will have a pretty simple database structure. Create a new table in phpMyAdmin named “short_links” with 5 columns. In the following order, name the rows: id, code, url, count, and timestamp. Be sure to set the id to a primary index with an auto increment.

URL shortener | create the database

include.php – defining all the global variables and custom functions

Let’s start by creating our include.php file. The first bit of code here is to just create some global variables that we can use to connect to the database and set some general site info, like the website address. The reason I am using GLOBAL type variables is so that these variables can be used across all the files/scripts that are linked to this include.php script. Making it so we only have to establish them once (aka “define”).

// define the global variables for the site
define("URL_LENGTH", 7);
define("URL_BASE", '');

// set the global variables for the database connection
define("DB_SERVER", 'localhost');
define("DB_USER", 'username');
define("DB_PASS", 'password');
define("DB_NAME", 'lesn_me');

// defene the character set for the url codes to generate from
define("CHARSET", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");

Notice the URL_LENGTH and CHARSET variables:

  • URL_LENGTH – this will determine the overall length of the special code that will be generated when the user created a short url. You don’t want to set it to be too short because you will not be able to support many saved urls. But also not too long, since we want these to be short urls.
  • CHARSET (aka character set) – this string will be used to randomly generate the unique codes. I like using the full character set of upper and lower case letters. This makes it so you can have more options.

Make a custom function to generate our codes

Next, we have our custom function named “generate_code”. As you can imagine, this will generate our random codes used in the url. If you want some clarification on custom functions, you can checkout the official documentation.

// function for creating the random string for the unique url
function generate_code(){
	// create the charset for the codes and jumble it all up
	$charset = str_shuffle(CHARSET);
	$code = substr($charset, 0, URL_LENGTH);
	// verify the code is not taken
	while (count_urls($code) > 0)
		$code = substr($charset, 0, URL_LENGTH);
	// return a randomized code of the desired length
	return $code;
  • str_shuffle() – we take our master CHARSET and jumble it all around so we can more easily get a random selection of the characters, saving it to the $charset variable.
  • substr() – we then take a sub string that is the exact length we want our codes to be.
  • while loop – then using a while loop, we make sure the generated code is truely unique in our database using a new custom function named “count_urls”. This loop will run for as many times as it takes to generate a unique code, and each time it runs, a new code is automatically generated.
Check this out:  Change user password for phpMyAdmin and Update MySQL account password

Make a custom function to count custom URLs

Our second custom function named “count_urls” will search in the database to count how many urls have been saved. And because of how the function is setup, we can either get the total number of urls in the database or just the number that have the code that was provided.

// function to count the total number of short urls saved on the site
function count_urls($code = ''){
	// connect to the database
	$conn = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
	// build the extra query string to search for a code in the database
	if ($code != '')
		$extra_query = " WHERE code='$code'";
		$extra_query = "";
	// count ow many total shortened urls have been made in the database and return it
	$count = (int) mysqli_num_rows(mysqli_query($conn, "SELECT * FROM short_links " . $extra_query));
	return $count;
  • first off we connect to the database, in the usual method.
  • $extra_query string – we create this string in the if statement so that we can append the end portion of the SQL query to be run. If the $code parameter was provided to the function when called, the $extra_query string will have the extra SQL query text to specifically search the database for the provided code. If $code was not provided, then the query will just count the total records in the database.
  • $count – simply counting the number of rows that are returned from the SQL query we run. For example, if a $code of “ABCDE” was provided then the SQL query would be “SELECT * FROM short_links WHERE code=’ABCDE’

Our last custom function named “validate_urls” is to simply make sure the user has provided a valid url. This function will be used later when we are processing the user’s form submission.

// function to perform all the validation needed for the urls provided
function validate_url($url){
	// make sure the user isn't trying to shorten one of our urls
	if (substr($url, 0, strlen(URL_BASE)) != URL_BASE){
		return filter_var($url, FILTER_VALIDATE_URL);
		return false;

index.php – the meat and potatoes of the whole show

The index.php file is divided into three portions: the short url redirect section, the javascript, and the form.

index.php – the url redirect section

This portion of the index file is the whole portion of the url redirection. It takes the unique code being supplied in the url and will search the database for the correct record. Then use a header redirect to send the user to the full url that is stored in the database.

	// require the include files that has all the back-end functionality
	// check to see if a code has been supplied and process it
	if (isset($_GET['code']) && $_GET['code'] != '' && strlen($_GET['code']) > 0){
		$code = $_GET['code']; 
		// validate the code against the database
		$conn = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
		$query = mysqli_query($conn, "SELECT * FROM short_links WHERE code='$code'");
		if (mysqli_num_rows($query) == 1){
			// retrieve the data from the database
			$data = mysqli_fetch_assoc($query);
			// update the counter in the database
			mysqli_query($conn, "UPDATE short_links SET count='" . ($data['count']) + 1 . "' WHERE id='". ($data['id'])."'");
			// set some header data and redirect the user to the url
			header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
			header("Cache-Control: no-cache");
			header("Pragma: no-cache");

			header("Location: " . $data['url']);
			$message = '<font color="red">Unable to redirect to your url</font>';
  • require_once() – this will load the include.php script into this file, allowing us to call the functions and use the GLOBAL variables inside of it.
  • if (isset… – with this if statement, we are checking to see if the GET information is being passed to the index.php script. If it is, then we will process the short url request as such.
  • $conn…. – connect to the database and run the search query to find the database record.
  • $data – stores the complete database record for the code provided
  • mysqli… – updates the database counter for the number of views the short url has gotten
  • headers() – sets the web page’s headers and redirects the user to the saved url. It is important that the headers be set before any text is displayed on the page. If any text is displayed, then the headers will be unable to redirect the user
Check this out:  Learn php string functions

index.php – the form

	<div id="wrapper">
		<div id="header">
			<h1>  <span class="seperator"> | </span> <span class="moto"> a simple url shortener</span></h1>
		<div id="content">
			<h3 class="topper">Just enter a url and click <i><u>"lesn me"</u></i>. That's it!</h3>
			<table class="mainForm">
				<form method="post" action="#" name="lesnForm" id="lesnForm">
						<td align="right"><input type="text" name="url" id="url" value="" placeholder="http://" style="width: 100%;" /></td>
						<td align="left" width="1"><input type="submit" name="lesnBtn" value="lesn me" /></td>
			<h3 id="message" class="success"><?php echo ( isset($message) ? $message : '' );  ?></h3>
			<div class="meta">
				There are currently <b id="counter"><?php echo number_format(count_urls()); ?></b> urls.
  • <div id=”header”… – the first bit of the HTML here is to setup some basic formatting and structure for the page
  • <div id=”content”… – this starts the beginning of the HTML structure for the actual content
  • <form… – finally we get to the form itself. Setting the method to POST makes it so the form will submit the data hidden to the user. Setting the name and id to “lesnForm”. These names are very important for later when we use the javascript to retrieve the data from and submit the form.
  • <input type=”text” … – this is the actual text box the user will enter their url they want to be shortened. Setting name and id to “url” will be how we get the text with the javascript
  • <input type=”submit” … – the submit button the user will check when they are ready to shorten their url
  • <h3 id=”message”… – this is where we will display any error or success messages to the user. It is important to note that the id is set to “message”.

index.php – the HTML head and javascript section

The next portion is that javascript magic that will handle the form submission to our back-end php script (aka the process.php). It is important to note that all of the code needs to go in the <head> portion of the page. You will also see that jquery and main stylehseet files are linked in the same area.

<link rel="stylesheet" type="text/css" href="./main.css"></link>
<script type="text/javascript" src="./jquery-3.3.1.min.js"></script>

	// ready the sites javascript for use after the page has loaded
		// process the form submission using javascript
			// get the url to be shortened
			var url = $("#url").val();
			if ($.trim(url) != ''){
				// submit all of the required data via post to the processing script
				$.post("./process.php", {url:url}, function(data){
					// process the returned data from the post
					if (data.substring(0, 7) == 'http://' || data.substring(0, 8) == 'https://'){
						// display a success message to the user
						$("#message").html('Your link has been shortened!');
						// update the counter shown on the page
						var counter = $("#counter").text();
						$("#counter").text(parseInt(counter) + 1);
			// select the text box after form submission
			// prevent the form from reloading the page
			return false;
		// select the text box on page load
  • $(document) … – this is the start of the javascript that. all of the javascript is wrapped inside of this function. This will allow the jquery to function properly.
  • $(“#lesnForm”).submit…. – here is where we use the javascript to process the form submission. the “#” symbol notes that the form id is named “lesnForm”.
  • var url …. – get the url the user entered from the text box
  • if ($.trim … – make sure the a url was entered in the form
  • $.post() … – using the jQuery post function lets us submit the form without having to reload the entire page, which means it will look seamless to the user. The first parameter the function takes is the name of the php script to process the data on the back-end. The second parameter is the form data to be submitted to the back-end script, for us this is just the “url” variable.
  • if (data… – here we process the results returned from the back-end script. With this if statement, we do a little bit of string validation. we are making sure that the url the user provided starts with “http://” or “https://”, because if the back-end script returns a url then it was successful. If the data variable contains anything that is not a url, then it is some sort of error message that will be displayed to the user.

If you put it all together and take a look at our custom URL shortener site, you will see our snazzy new site! Now just to make it all work on the back end!

Check this out:  Create a Member System in PHP
URL shortener | home page in action

process.php – back-end script to handle the form submission


// verify the url data has been posted to this script
if (isset($_POST['url']) && $_POST['url'] != '')
	$url = $_POST['url']; 
	$url = '';
  • require_once() – this will load the include.php script into this file, allowing us to call the functions and use the GLOBAL variables inside of it.
  • if statement – using the isset() function will return a true if the parameter has been created and a false if it has not. How it works for us is when the form has been submitted using the jQuery, the POST data will be set. If the form was not POSTed to this script, then the isset() function will return a false, which means the form was not properly submitted and therefore no “url” string will be provided. When the form is submitted, then we also make sure the “url” field from the form was filled out.

Validate the URL and add to the database

// verify that a url was provided and that it is a valid url
if ($url != '' && strlen($url) > 0){
	if ( validate_url($url) == true ){
		// create a connection to the database
		$conn = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
		// create all the variables to save in the database
		$id = '';
		$code = generate_code();
		$timestamp = time();
		$count = 0;
		$result = mysqli_query($conn, "INSERT INTO short_links VALUES ('$id', '$code', '$url', '$count', '$timestamp')");
		// verify that the new record was created
		$query = mysqli_query($conn, "SELECT * FROM short_links WHERE timestamp='$timestamp' AND code='$code'");
		if ($data = mysqli_fetch_assoc($query)){
			echo URL_BASE . $code;
			echo 'Unable to shorten your url';
		echo 'Please enter a valid url';
	echo 'No url was found';
  • if ($url…. – perform some basic string validation of user provided info just to make sure a url was actually provided.
  • if (validate_url…. – call to our validate_url() function we created earlier, this will just make sure a valid url was provided (e.g. has the “http” provided)
  • $conn – connect to the database and store the connection in the $conn variable
  • create the database variables – the next few lines are the miscellaneous variables that are used in our database’s table structure.
  • $result – run the query to INSERT the new record into the database. Any time you are using the SQL command of INSERT, you are saving the provided information into the database. But it is very important that the correct order and structure is given when you do it. If you don’t have the structure exactly right, the data will not be saved and you will get an error on the page, and nobody like to see error!
  • $query – now we run a new query to search the database for the record we just created (aka the one that has the exact code and timestamp). Then using the if statement, we get the database row and store it into the $data variable.
  • last but not least, we echo the entire url back to the user. This will make it so we can also display it back to the user using the javascript we used to submit the form.

.htaccess – enable the short urls

Using the rewrite engine in HTACCESS, we can make it so each of our short urls can be processed as normal links using php GET. For instance, when the user navigates to the short link of The url will be interpreted as going to

<Files .htaccess>
order allow,deny
deny from all

Options +FollowSymLinks
RewriteEngine on

# allow the url codes to be sent as get data
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?code=$1 [NC]

The Custom URL Shortener:!

Now with all the code written, we can take a look our completed custom URL shortener in PHP. And get some custom shortened URLs!

Download the FREE SOURCE CODE for this tutorial: Download Source Code
URL shortener | in action

11 Replies to “Create a Custom URL Shortener in PHP”

  1. hey there! , I adore a person’s composing therefore a great deal of! share we all keep in contact additional close to your posting on AOL? I require a specialist with this property to eliminate our problem facebook ads. Possibly that is definitely a person! Looking ahead to expert an individual.

  2. Randell says:

    I pay a quick visit each day a few web sites and information sites to read posts, except this web
    site offers quality based content.

  3. Jayden says:

    Hi, I do believe this is a great blog. I stumbled upon it 😉 I’m going to return once again since i have bookmarked it.
    Money and freedom is the greatest way to change, may you be rich and continue to help others.

  4. trans says:

    Excellent beat ! I would like to apprentice while you amend your web site, how can i subscribe for a blog web site?

    The account helped me a acceptable deal. I had been tiny bit acquainted of this your broadcast offered bright clear concept

    • Nick says:

      I am glad you liked the article. You can subscribe to the blog by clicking the email subscribe button at the bottom of every post.

  5. آموزش کودک دو زبانه says:

    Excellent post. I was checking continuously
    this blog and I’m impressed! Extremely helpful info specifically the last part :
    ) I care for such info much. I was seeking this particular information for a very long time.

  6. Yehia Waleed says:

    Can we have the source code?

  7. gimoz71 says:

    great, great tutorial !! i’ve only one issue, but since i’m not very skilled I don’t know why it happens: if I set id as primary key, it work only the first time, after that it returns me “Unable to shorten your url” and no record was added to db. but if I remove the primary key it all works except the fact there’s no increment, both id and count fields in the db.No code change, and I’ve double checked the db structure. Thanks a lot!

Leave a Reply

%d bloggers like this: