How To Add Custom Columns to the "All Posts" Screen (Or Your Custom Post Type) in WordPress

Posts, pages, comments, and even custom post types in WordPress rely on a screen often referred to as the “Edit Posts” screen, the “All Posts” screen, or sometimes, just edit.php. Here, you can get a list of all of your posts (of a given type) in a nice, clean table with sortable columns and pagination; from this table, you can edit, quick edit, trash, or view a given post, making it a very useful screen in managing any WordPress site.

You probably know exactly the screen I’m talking about, as anyone who has any experience with WordPress should be very familiar with it, but it’s at /wp-admin/edit.php for posts (and /wp-admin/edit.php?post_type=your_post_type for other types, including custom post types, where “your_post_type” is really your post type slug, e.g. “pages” or “events”).

But what if this table doesn’t include all of the columns you’d like? Maybe you’ve added a custom meta box to the the edit post screen, or maybe you have a custom post type (e.g. events) with meta boxes containing fields (e.g. start date and end date) that you’d like to incorporate into the table. Wouldn’t it be nice, for instance, to be able to see a “start date” column on your “All Events” screen, and even have the ability to sort the table entries by this date?

Custom Columns on edit.php Screen
This is what I’m talking about.

 

Well, you’re in luck, because this sort of thing is actually quite easy, even though the right documentation may be tricky to track down. All it requires is the use of three WordPress plugin hooks, consisting of two filters and one action. These can go inside your plugin, or, if you absolutely need to use a theme for this sort of thing (not really recommended), your functions.php file.

Step One: Add the Columns

Adding columns relies on the manage_${post_type}_posts_columns filter, which also lets you remove unwanted columns from the table (e.g. the publish date field, which may be confusing when seen next to start and end dates). Adding and removing columns is easy, as seen in the code example below:

<?php
/**
 * A filter to add custom columns and remove built-in
 * columns from the edit.php screen.
 * 
 * @access public
 * @param Array $columns The existing columns
 * @return Array $filtered_columns The filtered columns
 */
function myplugin_event_modify_columns( $columns ) {

  // New columns to add to table
  $new_columns = array(
	'start_date' => __( 'Event Start', 'myplugin_textdomain' ),
	'end_date' => __( 'Event End', 'myplugin_textdomain' )
  );
	
  // Remove unwanted publish date column
  unset( $columns['date'] );
  
  // Combine existing columns with new columns
  $filtered_columns = array_merge( $columns, $new_columns );

  // Return our filtered array of columns
  return $filtered_columns;
}

// Let WordPress know to use our filter
add_filter('manage_event_posts_columns' , 'myplugin_event_modify_columns');
?>

Just note that “myplugin” here should be a unique name for your plugin or theme. If your plugin takes an object-oriented approach and relies on class methods (e.g. if you’re using the WordPress Plugin Boilerplate, which I highly recommend), you don’t need to worry about the name being unique, but you will obviously need to adapt this code slightly (placing the function inside your class definition and adding the filter inside a “define hooks” method called from within your class constructor).

Step Two: Output the Table Cell Content For Our Custom Columns

If you’ve completed step one above and looked at your edit.php screen, you’ll notice that your new column headings are there but that the cells underneath these columns are empty. That’s because we still have to tell it what should show up!

For this, we need to use the manage_${post_type}_posts_custom_column action.

Here, we just need to check if the name of a given column matches one of our custom column names, and if so, echo the content we want to show up in those cells. For example, for my “Start Date” and “End Date” fields, I’m storing unix timestamps (seconds since Jan 01, 1970) as post meta data. So, in order to have the start date and end dates show up in my table, I just need to use WordPress’ get_post_meta() function to retrieve the stored value and, as long as the field value is not empty, convert it to a nice, human-readable date using PHP’s date() function (if the field is empty, I do not echo anything).

<?php

/**
 * Render custom column content within edit.php 
 * table on event post types.
 * 
 * @access public
 * @param String $column The name of the column being acted upon
 * @return void
 */
function myplugin_event_custom_column_content( $column ) {
  
  // Get the post object for this row so we can output relevant data
  global $post;
  
  // Check to see if $column matches our custom column names
  switch ( $column ) {

    case 'start_date' :
      // Retrieve post meta
      $start = get_post_meta( $post->ID, 'event_start', true );
      
      // Echo output and then include break statement
      echo ( !empty( $start ) ? date( "m/d/y h:i A", $start ) : '' );
      break;

    case 'end_date' :
      // Retrieve post meta
      $end = get_post_meta( $post->ID, 'event_end', true );
      
      // Echo output and then include break statement
      echo ( !empty( $end ) ? date( "m/d/y h:i A", $end ) : '' );
      break;
      
  }
}

// Let WordPress know to use our action
add_action( 'manage_event_posts_custom_column', 'myplugin_event_custom_column_content' );
?>

Once again, note that “myplugin” here should be a unique name for your plugin or theme, unless you’re taking an object-oriented approach (see above note).

You’ll obviously need to adapt this function depending on the sort of content you want to show up in each table cell (if you’re confused about my echo statement, see the PHP language reference for Ternary Operators and/or the PHP function reference for date).

Step Three: Make Our Custom Columns Sortable

Making your new columns sortable is an optional step, but it’s easy to do using the manage_edit-${post_type}_sortable_columns filter, which (at the time of writing) appears to be missing from the WordPress Plugin API Filter Reference.

<?php
/**
 * Make custom columns sortable.
 * 
 * @access public
 * @param Array $columns The original columns
 * @return Array $columns The filtered columns
 */
function myplugin_event_custom_columns_sortable( $columns ) {
  
    // Add our columns to $columns array
    $columns['start_date'] = 'start_date';
    $columns['end_date'] = 'end_date';

    return $columns;
}

// Let WordPress know to use our filter
add_filter( 'manage_edit-event_sortable_columns', 'myplugin_event_custom_columns_sortable' );
?>

One last time, note that “myplugin” here should be a unique name for your plugin or theme, unless you’re taking an object-oriented approach (see note under step one above).

If you’ve done everything correctly, that’s it! Your custom columns should be appearing on the edit.php page for your post type of choice; they should contain the values you’ve instructed them to output, and (if you’ve followed step three) they should be sortable by clicking on the column header.