Database Theory, WordPress Code Techniques

A Performant Way to Feature Posts

In a past blog post I explained why featuring posts using a taxonomy term is much more performant than using a meta query. The comment I get from people is “that’s awesome, but using tags to feature a post is not a good user experience”. I agree, attaching a “featured” tag to featured posts, while performant is not a good experience for users because it leaves room for error on the admin side and shows the “featured” tag to users on the front end (if you are listing your tags).

Thankfully, there is a much better way to do this. We can create a small meta box with a “Featured Post” checkbox. This checkbox will add/remove a term in a hidden taxonomy from the post. Here is what the meta box will look like in WordPress 3.9:

Featured post meta box

I will take you through the code necessary to set this up. First we need to register a private taxonomy for internal use:

function tl_register_taxonomy() {
  $args = array(
    'hierarchical' => false,
    'show_ui' => false,
    'show_admin_column' => false,
    'query_var' => false,
    'rewrite' => false,
  );

  register_taxonomy( 'tl_post_options', array( 'post' ), $args );
}
add_action( 'init', 'tl_register_taxonomy' );

Now let’s write the code that actually associates the taxonomy term with featured posts. This will hook onto the “save_post” action.

function tl_save_post( $post_id ) {
  if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_post', $post_id ) || 'revision' == get_post_type( $post_id ) )
   return;

  if ( ! empty( $_POST['additional_options'] ) && wp_verify_nonce( $_POST['additional_options'], 'additional_options_action' ) ) {
    if ( ! empty( $_POST['tl_featured'] ) ) {
      $featured = term_exists( 'tl_featured', 'tl_post_options' );
      if ( empty( $featured ) ) {
        $featured = wp_insert_term( 'tl_featured', 'tl_post_options' );
      }
      wp_set_post_terms( $post_id, array( (int) $featured['term_id'] ), 'tl_post_options' );
    } else {
      wp_set_post_terms( $post_id, array(), 'tl_post_options' );
    }
  }
}
add_action( 'save_post', 'tl_save_post' );

Next, we need to output a meta box with a checkbox. If this checkbox is checked, the post is marked as featured and the appropriate information is sent to the “save_post” hook on POST.

function tl_meta_box_additional_options( $post ) {
  wp_nonce_field( 'additional_options_action', 'additional_options' );
  $featured = has_term( 'tl_featured', 'tl_post_options', $post );
  echo 'Featured: <input type="checkbox" name="tl_featured" value="1" ' . ( ( $featured ) ? 'checked="checked"' : '' ) . '>';
}

Don’t forget we need to actually register our new meta box:

function tl_add_meta_boxes() {
  add_meta_box( 'tl_additional_options', 'Additional Options', 'tl_meta_box_additional_options', 'post', 'side' );
}
add_action( 'add_meta_boxes', 'tl_add_meta_boxes' );

Querying for posts on the front end is super easy! Here is an example query:

$query = new WP_Query( array(
  'tl_post_options' => 'tl_featured'
  'post_status' => 'publish',
  'post_type' => 'post',
) );

4 thoughts on “A Performant Way to Feature Posts

  1. How do you do this for more than one option?
    I tried (unsuccessfully) to create two functions, like the one above that uses the save hook (eg. tl_save_post1() and tl_save_post2() )

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s