Simple Pretty URL Using PHP htaccess (Step-By-Step Example)

Welcome to a quick tutorial on how to create a pretty URL system with PHP and htaccess. Showing the actual file name of scripts in the URL is ugly, and it is a security risk. If you are looking to create clean, human-friendly URLs, it actually isn’t that difficult to achieve – Read on for an example!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TLDR – QUICK SLIDES

Fullscreen Mode – Click Here

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

  • If not deployed in the base path, for example, http://site.com/PRETTY-URL/:
    • Edit .htaccess, change to RewriteBase /PRETTY-URL/ and RewriteRule /PRETTY-URL/ index.php [L].
    • Edit index.php and set define("URL_BASE", "/PRETTY-URL/").
  • Make sure that mod_rewrite is enabled in Apache.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

PRETTY URL WITH HTACCESS & PHP

Let us now get started with creating a pretty URL system with Apache Web Server and PHP.

 

REQUIREMENT) ENABLE URL REWRITE IN APACHE

apache/conf/httpd.conf
# Make sure that mod rewrite is enabled
LoadModule rewrite_module modules/mod_rewrite.so

# Make sure that AllowOverride is enabled
<Directory "D:/YOUR-HTTP-FOLDER">
  AllowOverride All
</Directory>

Before we get into the code, please make sure that the URL rewrite module is enabled with overriding allowed.

 

STEP 1) HTACCESS – REDIRECT EVERYTHING TO INDEX.PHP

.htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

First, create a .htaccess file in your project folder. That’s right, for you guys who have used WordPress before, look no further – This is exactly what WordPress does. What these mean in plain English:

  • Redirect everything to index.php .
  • But leave the existing files and folders be.

The whole idea here is to use PHP to load the requested page (or even fetch contents from the database).

 

 

STEP 2) PHP PAGE LOAD HANDLER

index.php
<?php
// (A) SETTINGS
define("URL_BASE", "/");
define("PATH_PAGES", __DIR__ . DIRECTORY_SEPARATOR . "pages" . DIRECTORY_SEPARATOR);
 
// (B) PARSE URL PATH INTO AN ARRAY
// e.g. http://site.com > [""]
// e.g. http://site.com/foo > ["foo"]
// e.g. http://site.com/foo/bar > ["foo", "bar"]
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
if (substr($path, 0, strlen(URL_BASE)) == URL_BASE) {
  $path = substr($path, strlen(URL_BASE));
}
$path = explode("/", rtrim($path, "/\\"));

// (C) LOAD REQUESTED PAGE ACCORDINGLY
// (C1) URL PATH TO PHYSICAL FILE
// e.g. http://site.com > index.html
// e.g. http://site.com/foo > foo.html
// e.g. http://site.com/foo/bar > foo-bar.html
if (count($path)==1) { 
  $file = $path[0]=="" ? "index.html" : $path[0] . ".html"; 
} else {
  $file = implode("-", $path) . ".html"; 
}

// (C2) LOAD PHYSICAL FILE
if (file_exists(PATH_PAGES . $file)) { require PATH_PAGES . $file; }
else {
  http_response_code(404);
  require PATH_PAGES . "404.html";
}

Not going to explain this line-by-line, but this script essentially “maps the URL path to the physical file”. For example:

  • http://site.com will load pages/index.html.
  • http://site.com/foo will load pages/foo.html.
  • http://site.com/foo/bar will load pages/foo-bar.html.
  • If the “mapping fails”, show a 404 page.

 

 

STEP 3) HTML PAGES

With the foundations all in place, all that’s left is to create a “pages” folder and add some pages inside.

 

3A) HOME PAGE

pages/index.html
<h1>HOME PAGE</h1>
<p>The dummy home page.</p>

 

3B) ABOUT PAGE

pages/about.html
<h1>ABOUT PAGE</h1>
<p>The dummy about page.</p>

 

3C) 404 PAGE

pages/404.html
<h1>PAGE NOT FOUND</h1>
<p>Opps. Page might have been abducted by aliens.</p>

 

 

EXTRA) PROTECTING THE PAGES FOLDER

pages/.htaccess
Deny from all

Users can still manually access the pages from the URL, for example, http://site.com/pages/about.html. So a small extra here, create a .htaccess file in the pages folder to deny public access.

P.S. PHP is still able to read and access the pages folder.

 

EXTRA BITS & LINKS

That’s it for the pretty URL system, and here are some extras that you may find useful.

 

MANY OTHER WAYS TO LOAD PAGES

The above is but a simple example of how page load can be handled in PHP. There are endless ways to do it, and here are a few more ideas:

  • Instead of a flat HTML page, create your own template system –
    • require PATH_PAGES . "HTML-TOP.PHP";
    • require PATH_PAGES . "REQUESTED-PAGE.PHP";
    • require PATH_PAGES . "HTML-BOTTOM.PHP";
  • Load content from the database
    • require PATH_PAGES . "HTML-TOP.PHP";
    • SELECT `content` FROM `pages` WHERE `url`="REQUESTED"...
    • require PATH_PAGES . "HTML-BOTTOM.PHP;
  • For you guys who are working on an eCommerce project, the path can be used to serve as the category or pagination. For example, http://site.com/pastas/3. $path[0] is the category, and $path[1] is the page number.
  • You can even use the pretty URL for an access check. For example, http://site.com/admin/pageif ($path[0]=="admin" && $_SESSION["user"]["level"]!=["admin"]) { NO PERMISSION }

So yes, feel free to change it however you see fit in your project.

 

HOW ABOUT OTHER WEB SERVERS?

If you are using IIS or NGINX – It is possible to achieve this as well. Just enable URL rewrite and “translate” the above .htaccess for your web server.

 

TUTORIAL VIDEO

 

LINKS & REFERENCES

 

INFOGRAPHIC CHEAT SHEET

Pretty URL With PHP htaccess (click to enlarge)

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope it has helped you to create a better website, and if you have anything to add to this guide, please feel free to comment below. Good luck and happy coding!

9 thoughts on “Simple Pretty URL Using PHP htaccess (Step-By-Step Example)”

  1. Hi,
    Building my site according to it Facebook scarper allerts: Bad Response Code
    URL returned a bad HTTP response code. Guess no scarper can scarp my pages as GoogleAdwords allso does not see the code I pasted on my contact page (guess it just se 404). Allthough the site runs nice in browsers.
    Any advice?
    Attila

  2. Lukas Himmelsvandrare

    Hello, thank you for sharing this. When i try to replicate this, I can not get it to work correctly. It loads the 404 page correctly if the url is mainfolder/ but does not load any of the other pages, instead i get: “The requested URL was not found on this server.” from apache. Any idea of what i might have done wrong?

    (Also, when i echo the file in step 3 after $file= $folder.$file; I get: “C:\xampp\htdocs\mainfolder\pages\mainfolder.php” for the URL mainfolder/)

  3. Hi again and thank you for taking the time. I have by now come over the initial obstacles and even think I could be basically done if it wasn’t for the internal linking to css, js, img folders … which seems to be thoroughly upset be the redirect. So I added, e.g., RewriteCond %{REQUEST_URI} !^/css … no help. Perhaps, if you are willing to do this, you could take a (paid) look at the project =URL REMOVED=

    1. Read step 2 carefully – The .htaccess file already excludes existing files and folders, it does not redirect CSS/JS/HTML/IMAGE/VIDEO/WHATEVER files. The problem lies somewhere else. Thanks for the possible job offer, but I don’t think most people will find it… “cost-effective” to hire a senior web developer. Good luck!

      https://code-boxx.com/faq/#hire

  4. hi there — thx for the tutorial, but … well, my php skills are limited, I am able to understand the php handler code in a step-by-step fashion but I fail to understand the bigger view. E.g. I managed to open the about page by hard-coding in the handler, but when I change its name to about.php it stops working and I have no clue why. How on earth would I implement the handler into some sort of page navigation with parameters, relative paths to images folder etc. … thx for inspiration…

    1. Read index.php section B carefully, the answer is right there.

      * Section A splits the URL path segments into an array – $path = explode("/", rtrim(URL PATH, "/"))
      * Section B is how we deal with $path. This example simply combines them to load an HTML file $file = implode($path, "-") . ".html";
      * We can change the entire Section B to modify the system behavior. For example, if ($path[0]=="admin") { CHECK IF USER IS ADMIN BEFORE LOADING PAGE }

Leave a Comment

Your email address will not be published. Required fields are marked *