Navigation

WordPress Theme Development: Post Mortem

Sunday, June 29th, 2008

So last night Anne and I rolled out a new theme for this little ol’ blog. If you’re reading this in a feed reader, come on over and check it out. I hope you like it.

The design phase began by looking on wordpress.com for themes. After locating the greatest WordPress theme ever and the second greatest WordPress theme ever, our mission was clear: Don’t have PHP parse errors on my blog and avoid pictures of me in sunglasses.

After designing the theme (which began with my decree that Palatino shall be used as the body text font), we began work on actually implementing the theme in WordPress. This turned out to be much harder than we initially thought, and it took us five or six hours to do.

First allow me to pimp two awesome tools which made doing this all in 6 hours possible: Dropbox and Coda. Coda needs no introduction. It’s the amazing single-window website editor from the fine, fine folks at Panic, Inc.. Dropbox is an awesome new way to collaborate and store files. Anne and I used it to share the files in the WordPress theme so we could both edit them without having to deal with sync issues or pasting text snippets back and forth on IM. It’s currently in private beta but they will be launching one of these days, as startups tend to do.

Anyway, during development, I encountered a couple really, really annoying “features” of the WordPress theme “engine”. I’m using air quotes because raw PHP is not much of a theme engine.

The first annoyance is that most of the post-related functions (e.g. the_title()) don’t return their value, they output it directly. Why this is, I have no idea, since PHP allows you to use the <?= ?> processing directive to print the value of the expression contained inside.

In one case I wanted to check the value of something before printing it to the screen. (Un)luckily I have a background in PHP so I knew it was possible. For those more fortunate than I, here’s a code snippet:

<?php
ob_start();
the_title();
$title = ob_get_contents();
ob_end_clean();
if ($title == "Untitled") {
    echo "The author could not come up with a better title. Really, dude?";
} else {
    echo $title;
}
?>

The keys are the ob_start(), ob_get_contents() and ob_end_clean() calls. ob stands for “output buffer”, and you can find more information about them on the ob_start() documentation page.

The second annoyance also had to do with the various “loop” functions. Functions like the_permalink() or the_time() expect that some magical global state (ugh) has been set up. This is called The Loop in WordPress theme parlance. In this instance I wanted to get information about posts outside the context of the loop. Luckily, the WordPress API provides a rather undocumented way of doing this:

<?php
$posts = $wpdb->get_results("SELECT $wpdb->posts.* FROM $wpdb->posts WHERE $wpdb->posts.post_status = 'publish' AND $wpdb->posts.post_type = 'post' ORDER BY $wpdb->posts.post_date DESC");
if ($posts):
    foreach ($posts as $post):
        setup_postdata($post);
?>

<?php the_title(); ?> by <?php the_author(); ?>.

<?php endforeach; endif; ?>

By combining the (aptly named) get_results() function with setup_postdata()1, you can make arbitrary queries on the database. I recommend taking a look at the database description. One thing I would like to point out is that it appears (from this angle, anyway) that you should use $wpdb->posts.column_name instead of referencing column_name directly in your SQL. Perhaps an attempt to provide insulation should the DB schema change?

Other than figuring out those two things I wasn’t much involved in the WordPressification of the design — that was done by the inimitable Anne K. Halsall, who is both totally radical and friggin’ sweet. Big ups to Anne!

I hope you all like the new theme, and that I never have to write another WordPress template ever again.


Update: At the suggestion of Peter Hosey I took a look at the query_posts() function. It appears to obviate the need, at least on my template, for doing any database queries. Hurrah!

I was also able to get rid of the ob_start() nonsense — I was using next_post_link() which does not have a get_ variant. Luckily, there are the also-undocumented get_next_post() and get_previous_post() functions, which return a database row object. So now I’m simply testing the return of those functions, and if they’re false, displaying my custom text. Check it out at the bottom of newest (or oldest) blog post.


  1. I can’t find any documentation, but it seems to just take a row from a database query as its argument. 

Comments

  1. Anne replied on June 29th, 2008:

    “I hope you all like the new theme, and that I never have to write another WordPress template ever again.”

    You and me both! Looks great though, congrats!

  2. Robert Accettura replied on June 29th, 2008:

    $title = the_title('','',false);
    

    When in doubt, Google it.

    Docs are good.

  3. Peter Hosey replied on June 29th, 2008:

    The first annoyance is that most of the post-related functions (e.g. the_title()) don’t return their value, they output it directly.

    And most of those (if not all of them) come in a “get_” version that returns the value. So, in this case, get_the_title.

    ob_start();
    the_title();
    $title = ob_get_contents();
    ob_end_clean();
    $title = get_the_title();
  4. Colin Barrett replied on June 29th, 2008:

    Perhaps I should have been more specific. I’m using the next_post_link() and previous_post_link(). There isn’t a display parameter nor is there a get_next_post_link() function.

  5. Colin Barrett replied on June 29th, 2008:

    I’ve updated the post with some new information. Thanks Robert and Peter!

  6. Josh replied on June 29th, 2008:

    My wife and I will soon be making our own template, and I’m more scared about it now than I was before I read this entry! I’m pretty handy with PHP, though, and she’s got a pretty cool design up her sleeve, so hopefully we’ll survive.

    I really dig the sparseness of this one. Nice work. It lets the text stay in the center as the focus and doesn’t distract me with a bunch of useless junk.

    (Do you really only have two posts, or are your archives broken?)

  7. Colin Barrett replied on June 30th, 2008:

    @joshlews The archives were broken. I’ve fixed them.

  8. WordPress Wednesday July 2, 2008 replied on July 2nd, 2008:

    […] here a brief look under the hood of one team’s experiences theming WordPress. Worth a look, if you ever want to play with a […]

  9. elena replied on August 4th, 2008:

    i’m triyng to do my own template so this informations helped me a lot..thanks very much Have a nice day