One of the exciting new features in WordPress 3.0 is custom post types. We can create our own post types by using the register_post_type function.
If we enable UIs for our custom post type, we will get additional menu items on our WordPress dashboard similar to the Edit and Add New options for standard posts.
Here, we consider how to add new columns to the Edit custom post type screen.
1. Create a Custom Post Type
Creating a custom post type is surprisingly straight-forward and well documented in the WordPress Codex.
In this example, we create a custom post type called gallery.
$labels = array( 'name' => _x('Galleries', 'post type general name'), 'singular_name' => _x('Gallery', 'post type singular name'), 'add_new' => _x('Add New', 'gallery'), 'add_new_item' => __("Add New Gallery"), 'edit_item' => __("Edit Gallery"), 'new_item' => __("New Gallery"), 'view_item' => __("View Gallery"), 'search_items' => __("Search Gallery"), 'not_found' => __('No galleries found'), 'not_found_in_trash' => __('No galleries found in Trash'), 'parent_item_colon' => '' ); $args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'query_var' => true, 'rewrite' => true, 'capability_type' => 'post', 'hierarchical' => false, 'menu_position' => null, 'supports' => array('title','thumbnail','excerpt') ); register_post_type('gallery',$args);
2. Add New Custom Post Type Columns
As shown in the screen-shot above, our custom post type Edit screen (called Gallery) starts off with four columns – checkbox, Title, Author, and Date.
To add new columns to our Edit screen, we want to hook into the manage_$pagename_columns filter. The $pagename of the Edit screen is edit-$post_type.
Therefore, in this example, –
- Edit page name = edit-gallery
- Add column filter hook = manage_edit-gallery_columns
Our add column function call looks like this –
// Add to admin_init function add_filter('manage_edit-gallery_columns', 'add_new_gallery_columns');
Our filter function accepts an array of column names, and returns our new column array once we are done.
function add_new_gallery_columns($gallery_columns) { $new_columns['cb'] = '<input type="checkbox" />'; $new_columns['id'] = __('ID'); $new_columns['title'] = _x('Gallery Name', 'column name'); $new_columns['images'] = __('Images'); $new_columns['author'] = __('Author'); $new_columns['categories'] = __('Categories'); $new_columns['tags'] = __('Tags'); $new_columns['date'] = _x('Date', 'column name'); return $new_columns; }
In the example above we fully replace the column array with our own entries. We can also just add columns by adding new elements into the existing $gallery_columns array. However, our added columns will only appear after the existing default columns.
The functions above will add new columns into our Edit Gallery screen which now looks like this –
If we want the column to be sortable, then we can use the manage_{$screen->id}_sortable_columns filter. Here is a good example for making sortable columns.
3. Render Our New Custom Post Type Columns
Note – In the screen-shot above, the ID and Images columns are empty because they are not standard WordPress post columns. Standard WordPress post columns include –
- ‘cb’ – Post checkbox.
- ‘date’ – Date when post was last modified.
- ‘title’ – Post title and common post actions including Edit, Quick Edit, Trash, and View.
- ‘categories’ – Post categories.
- ‘tags’ – Post tags.
- ‘comments’ – Number of post comments.
- ‘author’ – Post author.
To render our new columns, ‘id’ and ‘images’, we must hook into the manage_posts_custom_column action (in WordPress 3.0).
In WordPress 3.1, we want to hook into the manage_{$post_type}_posts_custom_column action. Since our example post type is gallery, we want to hook into manage_gallery_posts_custom_column.
// Add to admin_init function add_action('manage_gallery_posts_custom_column', 'manage_gallery_columns', 10, 2); function manage_gallery_columns($column_name, $id) { global $wpdb; switch ($column_name) { case 'id': echo $id; break; case 'images': // Get number of images in gallery $num_images = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->posts WHERE post_parent = %d;", $id)); echo $num_images; break; default: break; } // end switch }
Our ‘id’ and ‘images’ columns will now be rendered with the proper values.
We Are Done!
Another interesting action hook in the Edit screen page is restrict_manage_posts which allows us to control which custom post objects we want to show on the page.
And just like that … we are done!
Dasha says
I was also wondering what’s the difference between:
$new_columns[‘title’] = _x(‘Gallery Name’, ‘column name’);
and
$new_columns[‘categories’] = __(‘Categories’);
What does ‘column name’ when specified?
Thanks.
ShibaShake says
_x pertains to doing translations within WP. I really didn’t need to use it above. Likely, it was carry-over from some native code that I was looking at.
Here is a bit more on _x
http://phpdoc.wordpress.org/trunk/WordPress/i18n/_wp-includes—l10n.php.html#function_x
Travis says
I was wondering how one would add an edit function to each object in the custom category, just like the functionality on the standard post columns.
Thanks!
ShibaShake says
Try using the post_row_actions filter. Alternatively, you can create your own ‘title’ column by patterning it after the post ‘title’ column.
http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-admin/includes/list-table-posts.php.source.html#l475
Dasha says
Thanks for the great article, so hard to find tutorials on this topic!
I have 2 post types: ‘Portfolio’ (with meta_data) and ‘Client’. I’m adding custom columns to ‘Portfolio’ admin edit page:
add_filter(‘manage_edit-portfolio_columns’, ‘add_new_portfolio_columns’);
function add_new_portfolio_columns($portfolio_columns) {
$new_columns[‘cb’] = ”;
$new_columns[‘title’] = _x(‘Portfolio Title’, ‘column name’);
$new_columns[‘portfolio_types’] = __(‘Portfolio Types’); //Portfolio taxonomy
$new_columns[‘client’] = __(‘Client’); //reference Client post type via ‘client_id’ in Portfolio meta
$new_columns[‘testimonial’] = __(‘Testimonial’); //Portfolio meta into
$new_columns[‘date’] = _x(‘Date’, ‘column name’);
return $new_columns;
}
I have a problem that I can’t understand. I’ve specified my custom columns, all good, and here is the method that I use to populate the columns. It seems that after extracting ‘client_id’ from ‘Portfolio’ meta and finding ‘Client’ post type things go wrong. Because for the next column I’m exctracting ‘testimonial’ from ‘Portfolio’ meta, but it seems that $post is now a ‘Client’ post.
add_action(‘manage_posts_custom_column’, ‘manage_portfolio_columns’, 10, 2);
function manage_portfolio_columns($column_name, $post_id) {
global $wpdb, $post, $key;
switch ($column_name){
// PORTFOLIO post type columns
case ‘portfolio_types’:
$terms = get_the_term_list($post->ID , ‘portfolio_type’ , ” , ‘, ‘ , ” );
if(is_string($terms)) {
echo $terms;
}
break;
case ‘client’:
$portfolio_meta = get_post_meta($post->ID, $key, true);
$client_id = $portfolio_meta[‘client_id’];
// client specified – display his name
if($client_id){
$client = new WP_Query(“post_type=client&p=$client_id”);
//this loop seems to scrue up the value of $post for the following column… instead of ‘Portfolio’ post type, I somehow getting ‘Client’ and I dont understand why
if($client->have_posts()) { while($client->have_posts()) { $client->the_post();
the_title();
}
}
}
break;
case ‘testimonial’:
$portfolio_meta = get_post_meta($post->ID, $key, true);
echo $post_id;
$testimonial = $portfolio_meta[‘testmonial’];
if($testimonial){
echo $testimonial;
}
break;
default:
break;
}
}
Would really appreciate any help!
Thanks.
ShibaShake says
Do you have a column named client for your Client post type as well? If so, there could be problems.
The manage_posts_custom_column gets called while rendering *all* post type objects including posts, pages, and custom post types. You could do a post_type check in the beginning of the function to limit the scope of its operation.
RedsPriesee says
Hi, it’s nice here so I am just saying hi. I’ve been reading forum for a moment now.
Leo says
This is the code I used:
First adding this to function.php:
add_theme_support(‘post-thumbnails’);
add_image_size( ‘release-post-thumbnail’, 95, 95 ); //Custom Thumbnail size
Then this is my case:
case “cover”:
$custom = get_post_custom();
echo the_post_thumbnail( ‘release-post-thumbnail’ );
break;
morticya33 says
Hi Shiba,
Do you happen to know how to sort the column by ID or by some meta value added? 🙂
ShibaShake says
You can hook into the wp loop query request to do this. I usually hook into the ‘request’ filter hook. However, you must be careful with this because it will get run every time the WP loop (i.e., the wp function) gets called. Put in tight conditionals so that your orderby property only gets applied on the relevant pages.
Pierre says
Hi Shibashake,
is there’s a way to remove the integrated “categories” column to add the same one (categories) but with categories ordered by hierarchy (respecting the tree of categories) ?
And, if yes, how to do that ?
TIA.
Amicably,
Pierre.
ShibaShake says
To remove a column, in add_new_gallery_columns you would just
Then you would add your own column –
Finally in the manage_gallery_columns you would add your own category tree rendering function –
Pierre says
Thanks !!!
Everything is cool now 🙂 You’re the one !!
Thanks again Shibashake.
Amicably,
Pierre.
Pierre says
Hi Shibashake,
i’m really new in the discovery of Custom types and this is second time i found your website as a REALLY good ressource 🙂 !
You help me to found what i was searching for.
So, with this comment, i wished to thank you :).
PS. Do you know a way to add our custom(s) column(s) in a particular position ?
Amicably,
Pierre.
ShibaShake says
You will need to insert it at exactly that location in the array. I usually just create a new array, but you can also use php array operations e.g. array_splice, array_merge, array_push to achieve an element insert.
Maurizio says
array_splice doesn’t work with associative arrays. You can add your custom column at a chosen position defining the key before one you want your custom column to appear. For instance, if you want to add the custom column ‘Status’ before ‘column author’ you can do like this:
your_filter_function($columns) {
$insert_before = ‘author’;
foreach ($posts_columns as $key => $val) {
if ($key == $insert_before) {
$new_columns[‘status’] = ‘Status’;
$new_columns[$key] = $val;
} else {
$new_columns[$key] = $val;
}
}
return($new_columns);
}
alex says
Is there a way to create a filter like in the edit posts category filter?
For example a filter by a custom field?
Thanks a lot, your lasts post are amazing!
ShibaShake says
Hello Alex,
So you want to create a filter for each of your custom fields?
I would look into adding the apply_filters command and pass in the value(s) you want to modify. For example, if I want to modify the num_images value I could do the following –
Lane says
You could even grab the first thumbnail and add that as column. Great posts! Where do I donate?
ShibaShake says
Thanks Lane. In terms of donation, just link to us when appropriate and that would be more than enough. 🙂
Noe Ruiz says
Ahh, this is exactly what I’m trying to accomplish. How do you apply an image to the custom_columns function? I have a custom field value as the image url, I just need to pass that into the custom_columns function to display it on the cpt’s edit page. The search continues!
ShibaShake says
Just do somethiing like –
Noe Ruiz says
Thank you Shiba for such a quick response. I’m still trying to figure this out.
In place of $my_image_url how would I attach the custom field of “tuticon” to it?
Basically want an image in place of the tutorial icon file names.
Noe Ruiz says
I must be writing this completely wrong. Echoing out the custom field might not be the way to do this? I apologize for my lack of php knowledge, such a noob I know. I greatly appreciate your help!!
Noe Ruiz says
Thank you for your help Shibashake, sorry for all comments. The following solved my problem.
ShibaShake says
Glad it worked out Ruiz. I think some of the php got lost so my guess is you used wp_get_attachment_image?
Is that right? I will update your comment if that is the case. Thanks.
Freddie says
So what was your final answer to showing images from posts? I’ve been searching how to do this for days. I would love to see your final code!