WordCamp Seattle Contributor Day

Over 60 developers, designers and documenters came out on a beautiful Sunday to learn and make WordPress better. This is an amazing community, and it’s always such a pleasure to see it in action.

20140629-131320-47600235.jpg

20140629-131318-47598166.jpg

20140629-131323-47603605.jpg

20140629-131319-47599185.jpg


WordPress homepage settings trick: a simple, portable way to show a static homepage and a blog index

I’m sure there are quite a few ways to do this, but here’s the problem I recently encountered, and a solution.

I wanted to make an entirely portable theme with a non-standard (meaning not just a blog list) homepage, and a blog archive page (ie — an archive of all my posts) at a particular non-root URL — in my case http://www.something.com/blog.  I think this is a pretty common scenario, and the usual way to deal with it is to use the settings under Settings -> Reading -> Front page displays:

Screen Shot 2013-05-31 at 6.34.49 PM

So you’d create a couple pages, perhaps named “home” and “blog”, and use these and the home.php and front-page.php templates to create the desired effect.  But this solution did not make me entirely happy for a couple of reasons:

  • I find WordPress’ behavior under various combinations of these settings and various presences/absences of theme templates to be overly-complicated.  As you can see from reading about these settings, there are several combinations of conditions that can obtain, and the template cascade becomes a bit hard to describe in general.
  • Perhaps more importantly, I was going for portability here and did not want to require the presence of particularly-named pages for my URLs to work.  (Nor did I want the theme to create these pages on install — problems abound with that.)

Instead, I came up with the following solution, which I’m sure is not unique, but I’m quite sure is not really that well known.  (I’ll also note loudly that from a performance and technical point of view, it’s entirely possible that this technique may have various dark cosequences, and I welcome comments to that effect if I’ve overlooked something.)  

So here’s how to do this:

1.  Leave the Front Page setting on “your latest posts“.

2.  Include a front-page.php template in your theme.  This will always display when WordPress thinks you want the homepage.  In this template include the markup etc. for your homepage.

3.  Now the fun begins.  We need to trick WordPress into showing us the blog index page on a URL without using a page.  In my case, I use archive.php for listings like this, but in your case it might be something else, like index.php or whatever.  In functions.php, add the following code:

//set blog_index as a valid query variable
function add_blog_index_var( $v ) {
  $v[] = 'blog_index';
  return $v;
}

//use the archive template whenever blog_index is set
function set_blog_index_template() {
  if( get_query_var( 'blog_index' ) ) {
    include( get_template_directory() . '/archive.php' );
    exit();
  }
}

//rewrites for blog index
add_rewrite_rule('blog/?$', 'index.php?blog_index=1', 'top');
add_rewrite_rule('blog/page/?([0-9]{1,})/?$', 'index.php?blog_index=1&paged=$matches[1]', 'top');

//add filter for query var
add_filter('query_vars', 'add_blog_index_var');

//add action for template swap
add_action( 'template_redirect', 'set_blog_index_template' );

So what does this do?

We first write the add_blog_index_var to add the blog_index variable as a valid query var that will be retrievable by get_query_var() and set-able from the URL. This addition is done below by filtering add_blog_index_var. This is a required internal mechanism that WordPress uses to regulate what variables can make the leap from $_GET to the WP_Query object.

We then write a function called set_blog_index_template that forces the archive.php template to be used if the blog_index query var is set. This function is then attached to the action hook template_redirect.

The only thing left to do is to force WordPress to set this get variable at a particular URL … hence the two calls to add_rewrite_rule … one for /blog/ (in my case … it could be any URI for you) and one for pagination like /blog/page/2/ etc.

Remember to flush rewrite rules before expecting this to work. (See Daniel Bachhuber’s excellent Rewrite Rules Inspector plugin if you need to sort out just what’s going on with your rules.

I hope this is useful to someone out there — it took me a while to figure out a decent way to do this without supporting special pages or futzing too much with the homepage settings.


Grist Goes WordPress

We turned on the new WordPress version of our site today at Grist!  You can read about it here and here.  Perhaps now I can take a vacation.  Or, I can go to Indiana in January.  Don’t feel too bad for me though — a bright spring awaits.

In the meantime, check out this post about the growing popularity of WordPress.


Follow

Get every new post delivered to your Inbox.

Join 557 other followers