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:

[code language=”php”]
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’ );[/code]

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

[code language=”php”]
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’ );
[/code]

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.

[code language=”php”]
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"’ : ” ) . ‘>’;
}
[/code]

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

[code language=”php”]
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’ );
[/code]

Querying for posts on the front end is super easy! Here is an example query:
[code language=”php”]
$query = new WP_Query( array(
‘tl_post_options’ => ‘tl_featured’
‘post_status’ => ‘publish’,
‘post_type’ => ‘post’,
) );
[/code]


Comments

4 responses to “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() )

    1. Hmmm, not sure what you mean by more than one option.

      1. You created a meta box called ‘additional options’ with ‘featured’ as one of the options. How do you create more options like the one ‘featured’ option? So it’s a meta box with a few different options not just one.

        1. It really depends what you are trying to do. No hard and fast way to do it.

Leave a Reply

Your email address will not be published. Required fields are marked *