Hacking the WordPress Admin: Custom Columns

The WordPress admin panel changed from version to version, and 3.2 introduces an even newer look for the whole admin section. What hasn’t changed is the semantics, the data model and structure of what powers the admin area, and this is what backwards compatibility and “solid platform” is all about.

Today we’ll talk about the admin columns. Ones that live in the edit post and edit page screens inside those massive tables. The tables are generated on the fly, featuring hooks and actions for developers to take advantage of. There are several reasons to do so, since WordPress now powers books websites, real estate portals and many other setups that require more than just a post title, description and a list of tags.

Take books for example, you might want to show the ISBN number of the book, feature it’s cover, number of pages or it’s price, so that the website editors can easily spot the one they’re looking for in the list. Or real estate: property IDs, thumbnails, pricing, etc. I’m sure you’ll find your own reason to take advantage of your different content models, but in today’s post we’ll keep it simple. I’ll show you how to add the post thumbnail and the word count in two separate columns for the edit posts screen.

Understanding How Columns Work

Columns in WordPress’ edit tables are very powerful if used correctly, and you can power your own admin screens with WP_List_Table too! With WordPress list tables, you’ll get nice-looking, AJAX-powered, customizable tables, with pagination and screen options free of charge. But that’s an advanced topic which we’ll perhaps talk about in a different post. Today we’ll be working with the Edit Posts screen but before we start take a good look at it.

Take good look at the columns, use your browser DOM inspector to see how elements are structured, how columns are structured. Look at the different views of the table and finally note that there’s a Screen Options panel, where you can customize how many posts per page should be shown, which columns should be shown, and which ones remain hidden. The two columns that we’re going to add today will appear in that panel very soon.

Writing the Code

We’ll be working with your functions.php file in your theme folder this time, but keep in mind that the snippets will run well in plugins as well. I do think that any visual aspects, including the custom post types and custom columns should belong to a theme, rather than a plugin, since their usage in the theme is quite crucial, although depends on the situation.

We’ll start off with a hook to the after_setup_theme action and since we’re going to display a thumbnail image, we might as well display a nicely sized one, so let’s add a new image size called “edit-screen-thumbnail” which is cropped to 100 by 100 pixels, we’ll use that later.

add_action( 'after_setup_theme', 'my_theme_setup' );
function my_theme_setup() {
	add_image_size( 'edit-screen-thumbnail', 100, 100, true );
}

The List Table Actions and Filters

This is important. In order to get the most out of list tables, you should understand how it’s actions and filters work. I suppose you’re familiar with actions and filters overall and the ones that we’re going to use today are manage_edit-post_columns which is a filter, and manage_posts_custom_column which is an action.

The manage_edit-post_columns filter is run on the existing columns in the edit posts list table, meaning it will get the checkbox, title, description and so on in an associative array, where the key is sort of a column ID used by WordPress to identify the column contents afterwards, and the value is the column title which is displayed.

The manage_posts_custom_column is an action which runs when an unknown (or custom) column content is about to be printed. This action doesn’t run for the standard columns, but whenever WordPress encounters one that it is not aware of, it will attempt to use this action to output the contents. It’s passed in the column ID which I mentioned earlier as an argument.

So now that you’re familiar with the filter and action used, let’s start by adding a couple of new columns to the table, and then create the actual content for the entries to display in those columns.

Creating the New Columns

It’s best if you hooked to admin_init for the rest of the actions since these things get only displayed in the admin side of your website. This will help take some load off your website, but I’ll skip this part for brevity and jump directly to creating (or how I like to call it — declaring) the new columns.

add_filter( 'manage_edit-post_columns', 'my_columns_filter', 10, 1 );
function my_columns_filter( $columns ) {
 	$column_thumbnail = array( 'thumbnail' => 'Thumbnail' );
	$column_wordcount = array( 'wordcount' => 'Word count' );
	$columns = array_slice( $columns, 0, 1, true ) + $column_thumbnail + array_slice( $columns, 1, NULL, true );
	$columns = array_slice( $columns, 0, 3, true ) + $column_wordcount + array_slice( $columns, 3, NULL, true );
	return $columns;
}

As you can see, I’m altering the incoming $columns associative array and I’m using the array_slice PHP function to “inject” two of my columns. The thumbnail column will go right after the checkbox column, while the word count column will go right after the title column. I then return the new $columns array and here’s the result.

As you can see the contents for the columns are empty, but you can already toggle their visibility through the Screen Options panel. If you get confused with ordering the columns, use print_r to inspect the $columns array and see how array_slice alters it for you.

What’s left now is to print out the contents for each entry, and that’s what we’ll do next.

Displaying the Custom Columns Content

I mentioned earlier that the display is done through an action. The passed in argument is the column ID which we’ve set to “thumbnail” and “wordcount” in the previous step. So we’ll check for those IDs and print out the contents using simple functions and the content from the global $post variable.

add_action( 'manage_posts_custom_column', 'my_column_action', 10, 1 );
function my_column_action( $column ) {
	global $post;
	switch ( $column ) {
		case 'thumbnail':
			echo get_the_post_thumbnail( $post->ID, 'edit-screen-thumbnail' );
			break;
		case 'wordcount':
			echo str_word_count( $post->post_content );
			break;
	}
}

After you’ve done that your new edit posts screen should look similar to the following:

Note that if your posts had thumbnails before this code, they won’t be resized to 100×100 pixels, instead, WordPress will use the original images (which might be quite big) and size them proportionally. Use a plugin called Regenerate Thumbnails to resize and crop the existing image attachments.

Wrapping Up

Of course displaying a post thumbnail and the word count is not the best thing you can do with custom columns, but as stated in the beginning of this post, you can use this technique to really take your setup to the next level. Themes and plugins can benefit from custom columns. Think podcasts, videos, items for sale and audio length, video size, item price or number of purchases. All these can easily be squeezed into the edit screen with only a few lines of code.

Custom columns work especially great with custom post types where your authors and editors will have all the required info at their fingertips. And the best part of it is that they can customize the columns themselves — ones they want to see and ones they don’t, with a few clicks in the Screen Options panel.

That’s about it, folks! Hope you’ve learned something new today and hope you take advantage of these techniques in your next WordPress project. Feel free to share your thoughts or any questions you may have via the comments section below, and don’t forget to subscribe to our RSS feed and keep up with the latest around WordPress.