WordPress Sortable Admin Columns for Custom Posts

Adding custom columns to the admin tables for your custom post types is a good way to provide more information to your users. WordPress provides a flexible method to add data whether it’s meta values, taxonomies, images, ACF PRO fields, or anything else tied to your post types.

Modifying the Custom Columns for a Post Type

To modify the columns for a specific post type you can use the manage_${post_type}_posts_columns filter. In your functions.php file add the following (replacing mycpt in the hook with your custom post type name used in the register_post_type() function):


add_filter( 'manage_mycpt_posts_columns', 'set_custom_edit_mycpt_columns' );

function set_custom_edit_mycpt_columns( $columns ) {
  $date = $colunns['date'];
  unset( $columns['date'] );

  $columns['photo'] = __( 'Photo', 'my-text-domain' );
  $columns['custom_taxonomy'] = __( 'Custom Taxonomy', 'my-text-domain' );
  $columns['acf_field'] = __( 'ACF Field', 'my-text-domain' );

  $columns['date'] = $date;

  return $columns;
}

The filter passes the current $columns available to the post type in an array. You can modify the array however you’d like to add, remove, or modify what shows up in the table.

The above code example does a couple things:

  • Modifies the default date column to move it to the end of the table
  • Adds a photo, custom taxonomy, and ACF field to the admin table display

Adding Data to the New Columns

Now these columns will appear when viewing the admin listing for your custom post type, but there won’t be any data in them. To assign values for each column you can use the manage_${post_type}_posts_custom_column action. In your functions.php you would add:


add_action( 'manage_mycpt_posts_custom_column' , 'custom_mycpt_column', 10, 2 );

function custom_mycpt_column( $column, $post_id ) {
  switch ( $column ) {

    // display a thumbnail photo
    case 'photo' :
      echo get_the_post_thumbnail( $post_id, 'thumbnail' );
      break;

    // display a list of the custom taxonomy terms assigned to the post 
    case 'custom_taxonomy' :
      $terms = get_the_term_list( $post_id , 'my_custom_taxonomy' , '' , ', ' , '' );
      echo is_string( $terms ) ? $terms : '—';
      break;

    // display the value of an ACF (Advanced Custom Fields) field
    case 'acf_field' :
      echo get_field( 'my_acf_field', $post_id );  
      break;

  }
}

With the above code in place you should now have data displaying for each post. Nice!

A handy feature of the WordPress admin tables is the ability to sort them by column data. You can do this with your custom columns as well with some additional code.

Making Your Custom Columns Sortable

To make your custom columns sortable you’ll use the manage_edit-${post_type}_sortable_columns filter. In your functions.php file add the following:


add_filter( 'manage_edit-mycpt_sortable_columns', 'set_custom_mycpt_sortable_columns' );

function set_custom_mycpt_sortable_columns( $columns ) {
  $columns['custom_taxonomy'] = 'custom_taxonomy';
  $columns['acf_field'] = 'acf_field';

  return $columns;
}

All we’re doing here is setting the custom columns that should be allowed to sort, in this case the custom taxonomy and our ACF field. Now the column headers for these columns will appear as links and be sortable just like default WordPress columns.

Sorting Metadata

By default WordPress does a decent job of sorting the data, including taxonomies recently. However, for meta data (such as the ACF field we’ve added) it needs some guidance. To get things working as expected you’ll need to modify the query for the table data. For this we’ll be using the pre_get_posts action. In your functions.php add:


add_action( 'pre_get_posts', 'mycpt_custom_orderby' );

function mycpt_custom_orderby( $query ) {
  if ( ! is_admin() )
    return;

  $orderby = $query->get( 'orderby');

  if ( 'acf_field' == $orderby ) {
    $query->set( 'meta_key', 'acf_field' );
    $query->set( 'orderby', 'meta_value_num' );
  }
}

Here we modify the query if it is sorting by the acf_field column. It modifies the query to use the meta key acf_field that the ACF field is using in the database, and is expecting a numeric value when we set orderby to meta_value_num. If your meta value is a string you’ll want to set orderby to meta_value.