Adding Custom Columns to WordPress Post listing
Filed Under: Tags: actions, custom columns, filters, hooks, WordPress
In a reader comment one of my previous posts about “Adding columns to Taxonomy tables”. The commenter asks how to add columns to a normal Posts listing.
Well, readers here is the simple solutions. There are basically 2 hooks. One is a filter. The other an action. Below are examples of how to setup these hooks. I explain the details below the code listing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | add_filter( 'manage_edit-post_columns', 'admin_post_header_columns', 10, 1); add_action( 'manage_posts_custom_column', 'admin_post_data_row', 10, 2); function admin_post_header_columns($columns) { if (!isset($columns['note'])) $columns['note'] = "Notes"; return $columns; } function admin_post_data_row($column_name, $post_id) { switch($column_name) { case 'note': // Logic to display post 'Note' field information here. // $post_note = get_post_meta($post_id, 'note', true); //if ($post_note) echo $post_note; break; default: break; } } |
So what are these filters/actions function?
The first line, add_filter( ‘manage_edit-post_columns’… sets up a filter. This filter adds the new column to the listing. This filter is called only once when the page is loaded. Since this is a Filter WordPress will call our function ‘admin_post_header_columns’ and pass in a parameter. In this case the parameter is an array of columns. As part of our function we can change/add/delete items from the array then we MUST return the array. In our simple example all we are doing is adding an item to the array for our ‘Notes’ columns. As with any PHP array we assign a key to be ‘note’ and the column label ‘Notes’. Then return the array back to WP.
A note about the filter name. Notice we setup the filter as using the first parameter ‘manage_edit-post_columns’. Keep in mind this filter is specific to Posts. If you wanted to do this same thing for Pages you would instead use ‘manage_pages_columns’. Or if you were using a custom post type the value would be ‘manage_{$post_type}_posts_columns’ where ‘{$post_type}’ is your post_type. For example if we register a new post_type Products with the key ‘products’ then the filter would use the parameter of ‘manage_products_posts_columns’. On to the second hook. The action.
The second line of our code registers an action. While the previous filter added the column to the listing. This action gets called for each row of the displayed posts to display the contents in the row cell for that column. In WordPress an action is different than a filter in that your function may be passed some optional parameters but you are not expected to return any values. For our purpose we setup an action to the hook ‘manage_posts_custom_column’ which will call our function ‘admin_post_data_row’.
Inside our function we setup a case statement to switch on the column name. In our instance we only want to effect the ‘note’ column. This ‘note’ value is the array ‘key’ we defined in our previous filter function.
Back to the action hook registration. Notice the third and fourth parameters on this action registration call. The third parameter tells WordPress the priority of this hook o when to process it in relation to other hooks. A lower number means sooner a higher number means later. We set this to ’10′ which is a default value. The fourth parameter tells WordPress how many arguments to pass to our function. By default there will be only one argument, the column name. But since each row (post item) will have different values we need the second parameter which in this case is the ID of the post so we can look up the related custom field.
Also, like the filter hook where we setup the column there are different filters to call based on if you are using this on Pages, Posts or some custom post_type. In our case we are adding the column to the Posts listing so the first parameter of our hook is ‘manage_posts_custom_column’. If we were adding a column to Pages the parameter would instead be ‘manage_pages_custom_column’. And if we were adding this column to a custom post_type the parameter would be ‘manage_{$post->post_type}_posts_custom_column’ where ‘{$post->post_type}’ is the key to our registered post_type.
I hope this helps with a deeper understanding of WordPress and an appreciation of the wonderful world of WordPress actions and filters.
Pages-Children 1.5 released
Filed Under: Tags: hierarchical, plugin, post types, taxonomies, WordPress
Over the last week I’ve released 3 versions of my popular Pages-Children plugin.
Here is a breakdown of the changes.
1.3.1 – Fixed issues is plugin which were effecting the Media Library listing. As far as I can tell this was related to the update in WordPress 3.1.3
1.4 – Added support for any hierarchical post type. Previous versions of the plugin only worked for the default Pages. Now if you have any custom post type defined hierarchical you can have better formatting of the output.
1. 5 – In the previous version (1.4) I added support for custom post types. In this latest version I’ve added support for hierarchical taxonomies as well. Here is an example of a terms listing showing the breadcrumbs and navigation to ‘children’.
To comment or report an issue regarding this plugin please see the main project page for Pages-Children
Out of 1000 WordPress plugin developers I’m now ranked 372!
Filed Under: Tags: plugin, ranking, WordPress
Thanks to W-Shadow for putting together this nice page, http://w-shadow.com/files/top-1000-plugin-authors.html.
The page appears to be a mashup (do people still use that term) taken form wordpress.org plugin repository. The ranking on the page appears to be based on plugin downloads. Still out of 1000 plugin authors it’s nice to be in the top half. Though would be grateful to placement anywhere on the list. Thanks W-Shadow.
Media-Tags 3.0 plugin for WordPress Released
Filed Under: Tags: development, plugin media-tags, WordPress
I’m proud to say I’ve finally released Media-Tags 3.0 to the general public and it is available via the WordPress plugin repository http://wordpress.org/extend/plugins/media-tags/. Thanks to all who contributed ideas, bug reports and support in this milestone development. And my apologies for taking so long to get this out.
This plugin contains many new features. Some highlighted items are:
- Bulk Administration of media items This feature on both the Media > Library and Media Upload popup for the Post admin screen allow you to assign/remove Media-Tags to a selected group of media items. In previous versions you would need to edit each media item.
- Roles management Under the Media-Tags Settings panel is a new Roles management panel. This panel allows you to fine tune the access by individual users.
- Internationalization This is a much needed and requested features. Now all text handled by the plugin are using the WordPress i18n hooks to support translation into other languages.
- Removed over 1000 lines of custom code This old code was used to provide basic functionality for the tagging and URL rewrites. Since WordPress core functions have progressed over the last two years this custom code is no longer needed. This means the plugin will run cleaner and is more stable than previous releases.
- Better support for WordPress standard Taxonomy templates In the past the plugin has supported a custom theme template, mediatag.php. The plugin now support the more standard WordPress templates taxonomy-media-tags.php.
- A new Help section This new Help section provides many topics from general use to shortcodes tricks to template files support questions. Check it out.
- Many other features have been added. Too many to mention here.
Please leave all comments on the Media-Tags project page.
Adding Custom Meta Headers To Taxonomy Table Columns in WordPress 3.0
Filed Under: Tags: headers, meta, plugin, taxonomy, WordPress
This is part 2 of a series on digging deeper into the new WordPress Custom Taxonomies. In the previous article, “Custom Meta for new Taxonomies in WordPress 3.0“, I walked you through setting up the custom meta tables and the Taxonomy term editor form. In this part of the series I’ll show you how to add your new taxonomy meta fields to the taxonomy listing page.
Background
To bring everyone up to speed on the project I’m developing a simple product management system (e-Commerce) for a client. I wanted to take advantage of the new Custom Post Types and Taxonomies in the WordPress 3.0 system. I setup a new Post Type ‘Products’. As part of Products I’m defining a new Taxonomy ‘Product Packages’. A ‘Package’ is how a product is sold to the user. Think of threadless.com or some product site where you must select options like size or color. In our case each package has a number of extra ‘meta’ fields associated with it. In the case of my product packages some of these meta fields are unit price, shipping price, package active.
The goal of this article is to modify the default columns displayed on the taxonomy listing. These default columns are Name, Description and Slug. While these are sufficient for other taxonomies like post categories or post tags they don’t exactly work for my product package needs. What we will be building is some more like the following which includes meta field from part I. The column headers we will be added are ‘Active’ to show when a Product Package is on or off and the column header ‘Price’ which is the unit Price for a given package. These columns were chosen because the let the administrator visually see the information in the table form without needing to access each package detail.
So lets get started.
Adding Taxonomy Column Headers
We will start with adding the filter to modify the column headers. When I click on the ‘Product Packages’ I noted that URL for the taxonomy listing is
http://local.localsite.com/wp-admin/edit-tags.php?taxonomy=product_packages&post_type=products
After doing some digging I found that the edit-tags.php code calls a number of functions to build out the page structure. One of these function is ‘get_column_headers()’ The get_column_headers function is located in the /wp-admin/includes/template.php file line 674. Inside this function there are various checks to see if we are dealing with a normal build-in screen like for post categories or post tags. If not the logic falls down to line 761 there a filter is executed. The filename key or name is dynamic and is based on the taxonomy name. The filter key is ‘manage_’ . $screen->id . ‘_columns’. The screen->id value is the taxonomy name we used ‘product_packages’. The filter we will be setting up will be ‘manage_product_packages_columns’. So in our code’s init function we to subscribe to this filter and add a function to handle the processing. Below is the code. The init function you may recognize from part I.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | add_action( 'init', 'product_init' ); function product_init() { register_taxonomy( 'product_packages', 'products', array( 'hierarchical' => true, 'label' => __('Product Packages'), 'query_var' => false ) ); // Added from Part II. // This filter sets up a call to your function which will handle // adding (and removing) items from the columns array. This // filter passes up only one argument. The array of default headers. add_filter( 'manage_product_packages_columns', 'admin_product_packages_column_headers, 10, 1); } // Add this to your code's init function. This filter passes up // only one argument. The array of default headers. add_filter( 'manage_product_packages_columns', 'admin_product_packages_column_headers, 10, 1); // Add this function somewhere else in your plugin or functions file. function admin_product_packages_column_headers($columns) { // We are going to create a new array to hold the headers. // Below we take the checkbox column and the name column // and add to the new column array. Removing unwanted columns // and adding new one is trivial. The below method has // room form much improvement. $columns_local = array(); if (isset($columns['cb'])) { $columns_local['cb'] = $columns['cb']; unset($columns['cb']); } if (isset($columns['name'])) { $columns_local['name'] = $columns['name']; unset($columns['name']); } // We add the Package Active to the second column if (!isset($columns_local['product_package_active'])) $columns_local['product_package_active'] = "Active"; if (isset($columns['posts'])) $columns['posts'] = "Used"; $columns_local = array_merge($columns_local, $columns); if (!isset($columns_local['product_package_unit_price'])) $columns_local['product_package_unit_price'] = "Price"; return array_merge($columns_local, $columns); } |
This should get the new columns added to the display table. You can save your code and verify. The table headers will be displayed. But the row content will be empty.
Adding Taxonomy Column Data
The table row content is added using another filter hook. Again, once of the function called from within edit_tags.php is the core function tag_rows(); This function in turn calls other functions. Eventually, the flow ends up in _tag_row() in template.php line 398. Much like the header logic various checks are made to see if we are dealing with a built-in taxonomy. If not then a dynamic filter hook is executed at line 483. This dynamic filter like the header filter uses the taxonomy to name the filter key unique. The filter key is
‘manage_${taxonomy}_custom_column’. Again placing in our taxonomy key ‘product_packages’ the complete filter key will be ‘manage_product_packages_custom_column’.
So back to our code we add another add_filter command to out init function. Then we add a new function to process the filter request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | add_action( 'init', 'product_init' ); function product_init() { // From Part I register_taxonomy( 'product_packages', 'products', array( 'hierarchical' => true, 'label' => __('Product Packages'), 'query_var' => false ) ); // Added from Part II. // This filter sets up a call to your function which will handle adding (and removing) items // from the columns array. This filter passes up only one argument. The array of default headers. add_filter( 'manage_product_packages_columns', 'admin_product_packages_column_headers, 10, 1); // This filter sets up a call to display the contents of a Product Package row column. // The filter passes up 3 argument. We only use the second and third arguments. add_filter( 'manage_product_packages_custom_column', 'admin_product_packages_column_row', 10, 3 ); } // This function we check the column name then pull in the row data using get_metadata() function admin_product_packages_column_row( $row_content, $column_name, $term_id ) { switch($column_name) { case 'product_package_active': $product_package_active = get_metadata('product_packages', $term_id, 'product_package_active', true); if (!$product_package_active) $product_package_active = "yes"; return ucfirst($product_package_active); break; case 'product_package_unit_price': return get_metadata('product_packages', $term_id, 'product_package_unit_price', true); break; default: break; } } |
And that is it. At this point you should now see your taxonomy custom meta fields display in new column when listing your taxonomy items.




