Zach Schnackel

Extendable switch statements

Feb 9th, 2013

Throughout my base parent-theme, Basey, I was hell-bent on creating a DRY logic that was intuitive enough to handle the most complex setups, while not being too convoluted for the average user to get up and running. Inspired by Scribu's article on theme wrappers, I found several areas in my theme that should be needed to be pluggable.

One of my biggest crutches against WordPress' template system is the cluster-fuck of files that it takes to create a view. But it's the separation of these files that gives WordPress it's flexibility and awesome-sauce hierarchy system. So - I needed to bridge the gap.

One such example is single.php. This file is shows up pretty far-down the template hierarchy list and as expected, can be overridden with a plethora of different combinations/use-cases. One thing we can almost all agree on -- the surrounding containers for single-views rarely change throughout different post types. So, why don't we combine them into one? Yes, I completely understand a big list of if statements in a single file would be ridiculous; especially with all of the different types of content that can come with a single-view, but that's not my argument. My argument is about separating logic from function. Take the following example:

while (have_posts()) : the_post();
  switch($post->post_type) {
    case 'post':
      echo basey_single_post();
    break;

    default:
      echo basey_single_default();
    break;
  }
endwhile;

By calling the above inside of single.php, we're able to create different "cases" for each post type. This cuts down on duplicating wrapper HTML. "Great - less files. But where's the output stored?" Elsewhere - because what we're doing here is laying down a foundation for our views, not outputting them. In Basey, there is a separate output.php file that is used for this exact purpose. Let's take the above example a bit further.

As mentioned, Basey is a parent-theme, which means it isn't mean to be modified directly, but built on-top of. So where does that leave us with our single.php switch statements? The above example is pretty static. Although it gives us a bit more flexibility, any new custom post types we create are not included in this logic (and would ultimately fall-into the default case). That's where an extremely handy function called has_action comes into play. By combining this check with our original case statement, we are able to create a pluggable switch statement:

while ( have_posts() ) : the_post();
  switch( $post->post_type ) {
    case has_action( "basey_loop_single_{$post->post_type}" ) :
      do_action( "basey_loop_single_{$post->post_type}" );
    break;

    case 'post':
      echo basey_single_post();
    break;

    default:
      echo basey_single_default();
    break;
  }
endwhile;

What the above does is check for the existence of an action that follows the format of basey_loop_single_YOUR_POST_TYPE and if it finds it, perform that action.

Let's say you had a post type called movies. What you can now do is create a function like the following to handle your single-view for movies:

function basey_loop_single_movies_output() {
  echo '<h1>' . get_the_title() . '</h1>';
  the_content();
}
add_action( 'basey_loop_single_movies', 'basey_loop_single_movies_output' );

The following logic can be (and is in Basey) extended to other places in your template, like archive.php, creating reusable archive pages for different post types. The intricacies of design don't always allow these to be as clear-cut, but this has come in-handy during quite a few large site builds where reusable code was a must.