The other day I was checking out what folks are querying to get to my site.
Of course a ton of people get here looking for VPS comparison, but what surprised me was the volume of queries for “PHP routing”.
Back in 2015 I had posted a basic page rounding in PHP guide and as you’d expect, it’d pretty basic.
I’m not one of those people that goes back and massages old posts (outside of typos, thanks Justin) so I thought I’d take a moment to discuss some more advanced PHP routing techniques, specifically exploring optional and variable parts of the URI.
Please keep in mind that this is a discussion of how to handle URL routing in PHP without any additional dependencies.
It doesn’t have to be this way though! There are loads of framework-specific and stand-alone routing libraries out there, so if you’re just looking for a package to drop in, head over to Packagist and install Slim or whatever else suite you.
Okay, so last time I talked about using a big ol’
switch statement to
handle the routing based on the URI coming in.
First things first, I think it’s good practice to get a clean, non-query string
polluted URI. To do so, all you need to do is grab everything before the
the request URI:
Great, now that we have the URI sans-query string, let’s take a look at the different ways we could check against it:
Exact matches are easy, just check that the value is exactly that:
Obviously this would fall apart if you allow mixed-case URIs, if that’s the case, you can use a regular expression with the case-insensitive flag turned on:
Sometime you may want to only match part of a URI, generally the first part so that you can hand things off to another router. Works well if you like to group things a bit instead of having a single monolithic router.
Partial matches are very simple to accomplish and are very similar to our case-insensitive exact match:
Both exact and partial matches are easy to pull off. Where things get a bit more complex is when you start introducing variables.
It’s not hard to pull off a fuzzy match, where things get tricky is when you want access to the variable so you can use it in your code:
Of course, back at it again with the RegEx:
This isn’t without problems though. That regular expression will accept anything for the variable’s value. If we know the value will only ever be a number, we can improve things a bit (and gain a bit of validation in the process!):
Sometimes variable, sometimes not.
We’ve all done, it built out a page that handles adding a new entry as well as editing an existing entry. In those situations, we need to match the URI without a variable as well as with one:
This is where things get a bit messy. Since the regular expression has nested
parentheses, to group the slash with our variable and make the whole thing
optional, the variable winds up in the 3rd index of the
Not a deal break, just something to be aware of if you’re writing more advanced regular expressions to handle your routing.
Putting it all together
This is all well and good, but what’s it look like if we put it all together?
Easiest approach would be to just do a series of conditionals with a final else that handles 404 not found routing:
Is it elegant? Oh hell no. But it gets the job done.
If you are working with a very small project that has zero intention of ever getting larger, this is more than sufficient. But if you’re dealing with more than a handful of pages, I’d be shopping around for a routing library!