SEO friendly URLs with htaccess and PHP include script

Creating fancy SEO friendly URLs like is actually pretty easy and looks much better than In addition to looking more professionally, it might give you a small boost for your search engine visibility. This article is meant for PHP novices and will be pretty basic.

What you’ll need:

Before we begin, we will utilize PHP include() so we end up with 1 file as the template (index.php). All other sub pages will simply store the content and not the surrounding html/head/footer code.

So for the purpose of keeping things simple, I’ll paste all the code every step of the way so you can copy & paste it.

Step 1: Creating the template

Assuming your index.php looks like this:

<!DOCTYPE html>
<html lang="en">

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SEO Friendly URLs by IT-DB</title>
<link rel="icon" type="image/x-icon" href="res/favicon.ico">


<li><a href="index.php?page=home">Home</a></li>
<li><a href="index.php?page=portfolio">Portfolio</a></li>
<li><a href="index.php?page=about">About</a></li>
<li><a href="index.php?page=contact">Contact</a></li>

Welcome to our website!

Copyright © <?php echo date('Y'); ?>



We have to implement our PHP include function. Replace Welcome to our website! between the <main></main> tags with the following PHP script:

$page = !empty($_GET['page']) ? $_GET['page'] : '';
$page = substr(strtolower(preg_replace('([^a-zA-Z0-9-/])', '', $page)), 0, 20);
$def = "home"; // change to your default page
$dir = "inc"; // directory name containing all sub pages
$ext = "php"; // file extension if using anything else than php
if(!empty($page)) {
if(file_exists("$dir/$page.$ext") && is_readable("$dir/$page.$ext") && $page != "index") {
else {
header("HTTP/1.0 404 Not Found");
echo "Error 404 - File not found";
else {

It might look intimidating but it’s very simple. It checks if the URL contains ?page=x, and if so, it tries to show that page (file). It also does some input sanitizing as you can see in the second line (substr(strtolower(preg_replace('([^a-zA-Z0-9-/])', '', $page)), 0, 20);) to avoid hacking exploits. If the page (file) is not found, it will send error message 404.

Keep in mind that index should be saved as .php extension. If you save it as index.html the PHP code will simply not run.

Step 2: Setup URL rewrite using htaccess and mod_rewrite

Create a new file and save it as .htaccess. That’s right, no filename, only the extension. If using Notepad in Windows it might throw a fit because of a lacking filename. In that case, use another editor such as VSCode.

To keep things simple we’ll only use two lines to setup our URL rewrite. Copy and paste the following into your .htaccess file:

RewriteEngine On
RewriteRule ^([^/.]+)/?$ /index.php?page=$1

What this means is that any argument after / will be redirected to index.php?page=. Example: will redirect to (but your browser address bar will ofcourse only show

Step 3: Create the sub pages

Remember from last step, our PHP script defined “inc” as the name of our directory containing all sub pages. So, go ahead and create a directory called “inc” and then create a new file for every sub page by calling them subpage.php (i.e: Home -> home.php, About -> about.php).

Your file structure should look something like this

Keep in mind that these files should only contain the content related to that sub page. But they’re not limited to just text, you can use HTML and even PHP scripts inside them. Point is, you don’t have to declare the whole <html><head><meta> etc in every file, because that’s already saved in the template file and reused for every sub page.

Step 4: Change the URLs in index.php

While creating our template in the first step, we made a navigation menu like this:

<li><a href="index.php?page=home">Home</a></li>
<li><a href="index.php?page=portfolio">Portfolio</a></li>
<li><a href="index.php?page=about">About</a></li>
<li><a href="index.php?page=contact">Contact</a></li>

Although this will still work, we should change the URLs to use our new SEO friendly URLs. Change them to:

<li><a href="home">Home</a></li>
<li><a href="portfolio">Portfolio</a></li>
<li><a href="about">About</a></li>
<li><a href="contact">Contact</a></li>

That’s it, we’re done! Please let me know in the comments below if you encounter any issues or consult the troubleshooting tips.

Troubleshooting tips

Error “Object not found” or 404 error

Make sure you have mod_rewrite activated. If you recently installed mod_rewrite you may get away by just restarting the apache service. If not, check the guide I mentioned earlier:

I’m being redirected to the wrong page

This can happen if your project directory is in another subfolder. Please remove the / from the route in .htaccess:
RewriteRule ^([^/.]+)/?$ /index.php?page=$1
RewriteRule ^([^/.]+)/?$ index.php?page=$1

Thanks for reading!

Quick explanation of PHP property types

If you have little object-oriented programming experience in PHP you might be a little confused by all the new terms in OOP programming compared to regular functional programming. Before we begin, remember the difference between the terms initialize and instantiate. This is common for all programming languages, not just PHP.

Initialize = assign a variable to a value (all variables/properties must have an initial value when created, even if the compiler does this automatically)
Instantiate = create a new instance of an object (which could be assigned to a variable).

In other words, you could initialize a variable and assign it to a class instantiation. Now, take a look at the example class below with some methods to describe how they work in practice:

class ITDB
private function __construct()
// Constructor runs when class is instantiated,
// like this: $test = new ITDB();

private function hello1()
// Only accessible in current class
protected function hello2()
// Only accessible in current class AND
// child classes which inherits this one
public function hello3()
// Accessible to all classes

// By declaring the method as "static" we can call the
// methods without having to instantiate the class first
static public function hello4()
// Accessible without having to instantiate a
// new ITDB() instance first

ITDB::hello1(); // Will not work because method is private

$sayhi = new ITDB(); // Instantiate class, assign to $sayhi
$sayhi->hello1(); // Will not work, hello1() is still private
$sayhi->hello3() // This is valid, hello3() is a public method

ITDB::hello4(); // Also valid, hello4() is a public static method

Let me know in the comments if you have any questions regarding this 🙂

Composer failed to install Laravel because of missing zip extension

I was trying to install Laravel by running the command composer global require laravel/installer but it failed because laravel/installer v2.0.x requires ext-zip.

Turns out it wasn’t installed on my system. To fix it, first find out your php version by running php -v. Then use the php version number to install the missing extension like php7.2-zip

sudo apt install php7.2-zip

This will also work for other extensions like php7.2-mbstring and php7.2-dom

How to retrieve random posts from WordPress






This is just a quick solution I cooked up. Performance-wise it won’t be the best because it’s actually retrieving all posts, then shuffling the array and finally pick out 3 of them.

Here it is anyways:

function ShowRandomPosts() { 
    $get_random_posts = get_posts(); 
    echo '<div style="padding:10px;">'; 
    echo '<h3>Random posts</h3>'; 
    for($i=0; $i<3; $i++) { 
        echo '<div>'; 
        echo '<a href="'.get_post_permalink($get_random_posts[$i]->ID).'" style="color:#fff;">'; 
        echo '<img src="'.get_the_post_thumbnail_url($get_random_posts[$i]->ID).'" style="max-width:100px;"><br>'; 
        echo '<h4>'.$get_random_posts[$i]->post_title.'</h4>'; 
        echo '</a>'; 
        echo '</div>'; 
    echo '</div>';

Note that the HTML and inline CSS is just an illustration so you would probably want to change that.