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!

 

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

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

 

EXAMPLE CODE DOWNLOAD

Source code on GitHub Gist

Just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

 

PRETTY URL WITH HTACCESS & PHP

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

 

TUTORIAL VIDEO

 

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
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
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:

  • Rewrite engine on, redirect everything to index.php .
  • Don’t redirect HTTP authentication requests.
  • Also, leave the existing files and folders alone.

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.

 

EXTRAS

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.

 

LINKS & REFERENCES

 

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 }

Comments are closed.