02/07/2009 22:31 by mud ()
Most of our client work involves Rails development. It seems everybody wants a website that allow them to change the content, anytime, anywhere, whenever they like. But I always tell my clients to think about how often this “change” is going to happen. It’s certainly a waste of money to pay for developing some feature that you don’t end up using.
Even with Rails, having an “admin” backend requires extra design and development time. Also, with Rails and most other web frameworks, it’s not completely trivial to deploy and maintain these sites. For the client, it most likely means they need to ditch their current hosting provider and go with someone who will support Rails. Rails support on an affordable host is a hit or miss. I’m still surprised that Dreamhost still claims that they “support” Rails. In the world of VPS, the deployment is an easy thing, but for most clients, maintaining a VPS is a responsibility they don’t want. Why can’t it just work? I agree.
But this post isn’t about Rails. Instead, it’s about revisiting an oldie and ugly [but still sometimes a goodie] friend, PHP.
I just finished programming a site for Allen Hori. His site doesn’t require many updates but he did want to update it himself whenever he needed to. Having a simple configuration file along with good old FTP to upload files was the way to go. I know there are those people that love XML and XSLT, but I’m not one of them. I hate XML — it’s hard to read, hard to edit in a text editor and it’s bloated…and I XSLT? It’s not for me, and that’s all there is to say. My choice was YAML and PHP.
I feel like I abandoned PHP long ago, but I still write it when I prototype, before going to Rails. As a language, I think PHP is ugly, inconsistent and generally something that makes me appreciate how great Ruby is. But PHP still has a lot going for it. First off, every host supports PHP. It doesn’t matter if it’s a linux, solaris or MS, they all support it. Also, it’s fast and easy to deploy. Copy the files over to the server, and it does it’s thing. No need to start a server or restart a process after your shared host restarts the server without warning.
Okay, enough with the talk, now for the technical goodies.
Configuration
Each “gallery” page is configurable. You can specify images and captions. This is easily described in YAML like this:
title: Gallery Name
path: path/to/images
images:
- image: first.jpg
text: |
here's a caption for the first image.
- image: second.jpg
text: |
here's a caption for the second image.
Parsing this in PHP is easy. We just google for a PHP yaml parser. I chose spyc because it comes as one file that you simply include. No installation necessary. You simply parse the yaml file like this:
$config = Spyc::YAMLLoad('config/gallery.yml');
and magically, $config becomes a hash with the contents of the yaml file. That’s pretty much it, you can then go spaghetti style and insert content wherever you need. Whenever your client needs to update content, they just need to update the yaml file and upload any new images.
And…there’s more. Remember how this is a site that doesn’t change all that often? But we also don’t know when it will be updated. But with this current setup, every request will require PHP to do the same task. So being the responsible programmer, we need to implement caching.
Caching
We don’t know when Allen will decide to update the pages. But this is easy to determine. We know there was an update to the content any time the configuration file gets updated. So we need a way to generate a cache and update that cache anytime the configuration file is updated.
How do we do this? It’s actually really simple. Everything we need is built into PHP. To generate the cache, all we do is use PHP’s output buffer. It’s surprisingly easy; 1. start the buffer, 2. generate the page, 3. open a file handler, 4. write the buffer contents, and 5. flush the buffer to the browser.
ob_start();
// generate the page here
$fp = fopen("cache_file_location", "w");
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
This will save what’s sent to the browser to a file. To decide when to use the cache and when to generate a new one, we simply compare the file modification times of the yaml file and the cache.
if (file_exists($cachefile)) {
if (filemtime("config/gallery.yml") < filemtime($cachefile)) {
include($cachefile);
exit();
}
}
This will serve the contents of the cache file if the cache is up to date. Of course this conditional needs to run with every request, it will be much faster than having to evaluate the same PHP script over and over.

February 9th, 2009 at 16:59
Nice. I’m increasingly recommending to clients that they don’t need a full-blown CMS solution. Something like this is perfect for portfolio sites, especially when the client doesn’t want to have to rely on me for occasional updates.
February 16th, 2009 at 12:53
I’ve been following BuzaMoto since I stumbled upon MudCorp a few years back.
Very recently I’ve been dusting off old code to re-develop a personal project and this post has been very inspirational (PHP) and informational (thanks for the caching tip). Going to have to take a closer look at YAML as I’ve only ever dabbled with XML/JSON.
As always, keep up the great work guys.