Experiments with PHP: Re-factoring Blogfile
Blogfile is a simple PHP blog which I wrote in my spare time, and which (as mentioned under the menu on the left) is powering this blog.
It was largely experimental, and I didn't really hold myself to the highest standards of code quality. I just wanted to build a basic blog in a single PHP file, and didn't really put much thought into "properly".
That being said, it's worked well so far. It runs fast, has a low footprint, and has survived a few onslaughts from Hacker News (and other places). It stood up well to a few periods of 20000k hits in a day (not common, but apparently I pissed HN off a few times). This isn't a really huge amount, but for it to hum along nicely on shared hosting... well I'm not sure that wordpress would handle it as well.
If it's working so well, why would I re-factor it?
Because it's no longer just standard blogfile. I've changed it from stock to better suit my own needs and priorities. I've added features (like the RSS Feed) that aren't in the standard blogfile because I don't need them, but they're nice to have.
And also because it's still an experiment. The perfect place to experiment with ideas is somewhere that gets real-world use, but doesn't really matter. I'm not about to start trialling new tricks in a customer's code base (at least without their say so, and them being aware of the risks), and making small test scripts can give me a theoretical basis, but won't tell me how it performs under real world pressure.
So let's explore what I've done with this re-factor.
The first thing I did was switch the mysqli library for the PDO library. I used mysqli in the original blogfile as an experiment, and I can't honestly say that it's an improvement over using the original mysql_* API intelligently. I found the whole thing to be clunky and awkward (what, you want to run another query before you've finished with the result set of a previous query? Preposterous!)
PDO, on the other hand, has proven to be useful, clear, and consistent. I can create prepared statements, put them aside, and use them again later. I can use prepared statements (I'm sure that the mysqli library could handle it too, but it looks to be a cludgy mess). I can bind parameters as well as values to a query, which makes running multiple, different, queries a breeze. For example, here's the original blogfile code for counting a user's comments:
And here's the new code using PDO:
Almost half the length, and no more UNIONs. I'll call that two separate wins. You may also notice the power of
bindParam. I bound the variable
$v to the query, then I can change
$v, re-run the query, and it uses the new value of
$v instead of the value at the time of binding.
Late static binding
This is a new feature in PHP 5.3 (which I can use, thanks to DreamHost allowing me to pick my PHP poison). Normally in PHP, when using class inheritance, referring to a static variable from a method with
self::$foo would reference the variable that was defined in the same class as the method itself. This means that when a child class inherits that method, even if it overwrites the static variable, the method will still find the variable from the original class. For example:
This isn't very good for clean code, obviously. It means that you would have to re-define functions for child classes just to be able to access static variables defined there.
Enter late static binding.
Late static binding allows you to call a static variable that is defined in the class that you're using, not the class that you're writing. It lets you create sub-classes easier by simply re-defining the static variables, without having to redefine the methods that use them. Best of all, there's no massive overhead of code to use them. Simply replace
Using this, I've been able to create simple and succinct class definitions for pages and posts that allow me to re-use as many functions as possible, without having to write unnecessary wrapper code.
I've done a whole bunch of other upgrades to the code base, and I'm probably not entirely finished yet. Next, I'll be overhauling the dispatch system because using a switch statement to control your views is really bad for readability. The aim is to replace it with a system that will allow me to define dispatch functions, then let the script auto-magically find the correct function to call for each page.
So when will these upgrades be available in the standard blogfile? No idea, to be honest. Although PDO would be a great step forward, late static binding would only work in PHP 5.3 or higher which (as sad as this makes me) isn't actually available yet on many, many cheap web hosts. I could release one version with late static binding, and one with messy override functions, but then I'll have two versions of blogfile to maintain (well, three considering my customizations).
Instead, I'm kind of looking forward to seeing what other people can do with it. I've already had word from a number of people who have remixed and ripped blogfile to bits to suit their own needs. This is what it's for.
Let's see what you can do.