Adding custom sortable columns to your WordPress custom post type

With custom post types you often make more use of custom fields (meta data), and you want that to be part of the user interface. The traditional columns that come with blog posts just don’t meet your needs any more.

As of WordPress 3.0 the core now invokes filters based on your custom post type, which allows you to target your filters specifically for that post type. For example, if you want to filter the columns for your artists post type, the manage_edit-artists_columns filter is invoked. And if you want to make your columns sortable, then use the manage_edit-artists_sortable_columns filter.

I’ll add an example for my fictional artists post type. I have decided to add nationality to as a custom field, and I want it sortable. There are four steps

1. Add the custom column.

add_filter('manage_edit-artists_columns', 'tcb_register_artists_columns');
function tcb_register_artists_columns($columns){
  $columns = array(
    'cb'              => '<input type="checkbox" />',
    'title'           => 'Name',
    'nationality'     => 'Nationality',
  );
  return $columns;
}

2. Handle the custom column – what to display.

add_action('manage_posts_custom_column', 'tcb_handle_artists_columns');
function tcb_handle_artists_columns( $column ){
  global $post;
  if( $post->post_type != 'artists' ) return;
  if( $column == 'nationality' )
    echo get_post_meta( $post->ID, 'nationality', true );
}

3. Make the custom column sortable.

add_filter('manage_edit-artists_sortable_columns', 'tcb_register_artists_sortable_columns');
function tcb_register_artists_sortable_columns( $columns ){
  $columns['nationality'] = 'nationality';
}

4. Handle how to sort your custom column.

add_filter('requests', 'tcb_handle_artists_column_sorting');
function tcb_handle_artists_column_sorting( $vars ){
  if( isset($vars['orderby']) && 'nationality' == $vars['orderby'] ){
    $vars = array_merge( $vars, array(
      'meta_key' => 'nationality',
      'orderby'  => 'meta_value'
    ));
  }
  return $vars;
}

Codex references: