Basic page routing in PHP

Last week we talked about setting up a local development server with PHP’s
built-in web server and I mentioned that we’d delve into page routing. Routing
refers to taking the URI that a person was requested, let’s say /about and
routing that to the appropriate code.

Sure, you could just have a script named about.php and just make the .php
part of the URI. You could take it a step further and write a rewrite rule for
nginx or Apache or whatever and have that strip the .php so it’s just
/about. This is great, but if you are using the PHP web server you must build
your routing in PHP instead.

To get started, let’s create a new directory called routing with two
directories inside there, public and views, and change to the public
directory and start our web server:

mkdir -p router/public router/views
cd router/public
php -S localhost:3000

If you point your web browser to http://localhost:3000 you will receive a
“Not Found” message. That will tell you it’s working and we can get to work!

First, let’s create three views, one of the home page, one for the about page
and a third that will be our 404 page. You’ll need another terminal window and
should be in the root of the project (the router directory) we created
earlier. Once there, run:

echo 'home is where the heart is' > views/home.php
echo 'this is a site about nothing' > views/about.php
echo 'oh noes!!~!' > views/404.php

Now that we have our views ready, let’s set up our router. The router code will
live in public/index.php and should look something like this:

<?php
// Grabs the URI and breaks it apart in case we have querystring stuff
$request_uri = explode('?', $_SERVER['REQUEST_URI'], 2

// Route it up!
switch ($request_uri[0]) {
    // Home page
    case '/':
        require '../views/home.php'
        break
    // About page
    case '/about':
        require '../views/about.php'
        break
    // Everything else
    default:
        header('HTTP/1.0 404 Not Found'
        require '../views/404.php'
        break
}

Once you have that saved, go back to your browser and refresh it. You should
see the contents of the home page. If you go to http://localhost:3000/about
you should see the about page contents and for any other URI the 404 page (with
the appropriate HTTP status code header).

That’s page routing in it’s most basic form. If you want to add more pages, you
can add them to the switch statement. If you would much rather have a huge
monolitic file, you could even omit the require and inline the code right
there (which I don’t advice).

The only caveat I have ran into with this code is that if you try to access a
URI with a period on it, like about.php it will give you the internal PHP
web server’s “Not Found” message. This really shouldn’t be an issue on a web
server like nginx because you would just be routing all non-matching traffic to
the PHP process manager (regardless of the period).

Personally, I really like handling routing in PHP because it allows me to be
somewhat web server agnostic. I prefer nginx but perhaps down the road
something even better will pop up. When that happens, I would have to port all
of my web server specific configuration over to the new server. If the logic
lives in PHP I can just swap out the server and be pretty much good to go.

Remember, there this post is just an example of how to write some very basic
routing. I used this approach when I rewrote HolidayAPI because
it’s just 2 pages: home and the API end point. For more complex applications
you will most likely want to delve into using regular expressions to embed UIDs
and other variables into your URIs. I would highly recommend searching the web
for a routing library for anything more advanced.

Perhaps I’ll review some routing libraries down the road 😉

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.