Recent Posts


On WordPress’s Posts Loop


Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

I need a quick “non-quickies” post to unjam a page generation issue with this website so why not use it as an excuse to talk about how I create this website?

I have a WordPress install that runs locally on my computer. Once a day I use a command line script to generate a full static site from this system and then rsync those files to a generic web host (currently’s cheap-o $6/month hosting).

The command line script is a custom wp-cli command I wrote that uses code from Leon Stafford’s old WP Static HTML Output CLI plugin to generate the files. It looks like this plugin is no longer available and that Leon has newer projects for statically generating a site. It’s an easy bet that these newer projects eclipse what I’ve done for myself.

I built all this back in late 2016 when I was considering a full-time job with Automattic and wanted to get a feel for what deep customization of a WordPress system might look like. Keeping the system off the internet and only publishing static files means there’s a whole class of security vulnerabilities I don’t need to worry about. It also means I’ve been able to linger at version 4.7.21 using old plugins that didn’t make the 5.x/Gutenberg jump. Trade-offs on a personal project are often different than trade-offs for client work.

One of the custom features on my site is the “Programming Quickies” category. I used to have a number of independent blogs (Tumblr, paid, etc.) where I posted quick, one off bits of content about programming in a particular system. I kept these separate from my main site in order to keep “the brand” here about deep in-depth tutorials. I eventually decided I’d rather have these posts under my main site.

This presented a problem — I didn’t want these short posts to be the first thing someone saw when they came to my homepage. I wanted someone to see my latest single long post. I achieved this with a simple (if perhaps too expedient) theme change in a WordPress template file.

<?php while(have_posts()) : the_post(); ?>
    <?php if(get_post_format() === 'link'){ continue; } ?>
    <?php if(in_category('Programming Quickies')){ continue; } ?>
    <?php get_template_part('layouts/posttitle'); ?>
    /* ... */
    <?php break; ?>
<?php endwhile; ?>

WordPress PHP themes use The Loop to display posts. By default (at least in my version), the WordPress homepage would loop through the latest 20 posts and display them all. My original customization was to break out of this loop after rendering a single post.

<?php break; ?>

When I started writing more than plain long tutorials (link posts, Programming Quickies posts, etc), I added these guard clauses to The Loop

<?php while(have_posts()) : the_post(); ?>
    <?php if(get_post_format() === 'link'){ continue; } ?>
    <?php if(in_category('Programming Quickies')){ continue; } ?>

These basically say “hey, if this post isn’t a link post or a quickies post, move on the the next post”.

This worked well for almost five years — but today I woke up to a blank homepage.

The problem? WordPress loads and displays a set number of posts at a time. At some unknown point in time I’d configured this to be twenty posts. Before today, I’d never written more than twenty quickies posts in a row. Today, because there were twenty quickies posts, this meant the loop continued until there were no posts left. The result was a blank homepage.

The quick solution? Bump the number of posts per page in Settings -> Reading up to 21.

The medium term solution? Get a new non-quickies post published (you’re reading it).

Long term — the right thing to do here would be to figure out how to customize the global query used by The Loop on just the home page and exclude posts whose format is link and whose category is Programmer Quickies. I knew this was the right thing to do when I made the quick continue hacks above, but because I never went a few weeks without a long post I decided on the quick-fix rather than spend a day or two to figure out the right way to safely customize this behavior.

I’m sure WordPress pros are rolling their eyes at my timeline for what, to them, is a simple customization. The challenge here for an experienced programmer who’s not a WordPress expert is fearing all of WordPress’s global state. It’s hard to be sure that this sort of customization won’t leak out and break something else. Even when you quickly Google a tutorial you’re left wondering if they’ve provided all the guard clauses for the pre_get_posts hook.

Once I think about spending more than a day on a personal project I start thinking “maybe it’s time to move everything out of WordPress or at least upgrade to a more modern version”, and then personal project inertia kicks in.

Copyright © Alan Storm 1975 – 2022 All Rights Reserved

Originally Posted: 7th September 2021