Custom post types is a new and powerful feature in WordPress 3.0. Here, we consider how to add metaboxes to the new custom post type user interface.
There are three general classes of metaboxes that we may add to our custom post type screen –
- Built-in metaboxes – These metaboxes are built-in to custom post types, and can be easily added by calling the add_post_type_support function or by including them in our register_post_type function call.
- Taxonomy metaboxes – These are metaboxes associated with WordPress taxonomy objects. For example, two standard WordPress taxonomy objects are category and post_tag. Both have metaboxes defined, which we can include into our custom post type interface.
- Custom metaboxes – These are fully custom metaboxes that we create specially for our plugins or themes. They will usually contain HTML form elements that allow users to specify additional attributes and data for our custom post types.
1. Built-in Metabox
There are a variety of metaboxes that are built-in to custom post types.
- ‘title’
- ‘editor’ (content)
- ‘author’
- ‘thumbnail’ (featured image) (current theme must also support post-thumbnails)
- ‘excerpt’
- ‘trackbacks’
- ‘custom-fields’
- ‘comments’ (also will see comment count balloon on edit screen
- ‘revisions’ (will store revisions)
- ‘page-attributes’ (template and menu order) (hierarchical must be true)
[List taken from the WordPress Codex]
We can include built-in metaboxes during the creation of our custom post type object –
$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);
Line 24 – The support argument specifies which of the built-in metaboxes we want to include in our custom post type interface. Here, we include title, thumbnail, excerpt.
We can also include built-in metaboxes by using the add_post_type_support function.
add_post_type_support('gallery', 'title'); add_post_type_support('gallery', array('title', 'thumbnail', 'excerpt') );
The first argument is our custom post type and the second argument is the built-in metabox name(s) (can be a string or an array).
2. Taxonomy Metabox
We can add taxonomy metaboxes (e.g. category, post tag) to our custom post type interface by including them in our register_post_type function call.
$args = array( 'labels' => $labels, ... 'taxonomies' => array('category', 'post_tag') ); register_post_type('gallery',$args);
Alternatively, we may use the register_taxonomy_for_object_type function.
register_taxonomy_for_object_type( 'post_tag', 'gallery'); register_taxonomy_for_object_type( 'category', 'gallery');
Once we register an existing taxonomy with our custom post type, metaboxes are automatically added for that taxonomy. Below, a new Category and Gallery Tag metabox have been added to our custom post interface. The relevant taxonomy inputs will also be automatically saved, when we save our custom post object.
Note – The category and post_tag taxonomy objects each have their own special metabox interface. However, all other taxonomy objects will just use the standard WordPress post_tag interface.
If we want to replace the standard post_tag metabox with our own metabox, we may use the add_meta_box function which we will consider next.
3. Custom Metabox
Here, we create a custom metabox for our gallery object. In particular, we want to add a metabox containing a set of radio buttons so that users may choose what type of objects they want to store in their gallery (i.e. gallery type).
For example, they may only want to store attachments, or they may also want to store posts, pages, and even other galleries.
<?php // Add meta box goes into our admin_init function add_meta_box( 'gallery-type-div', __('Gallery Type'), 'gallery_type_metabox', 'gallery', 'normal', 'low'); function gallery_type_metabox($post) { $gallery_type = get_post_meta($post->ID, '_gallery_type', TRUE); if (!$gallery_type) $gallery_type = 'attachment'; ?> <input type="hidden" name="gallery_type_noncename" id="gallery_type_noncename" value="<?php echo wp_create_nonce( 'gallery_type'.$post->ID );?>" /> <input type="radio" name="gallery_type" value="any" <?php if ($gallery_type == 'any') echo "checked=1";?>> Any.<br/> <input type="radio" name="gallery_type" value="attachment" <?php if ($gallery_type == 'attachment') echo "checked=1";?>> Only Attachments.<br/> <input type="radio" name="gallery_type" value="post" <?php if ($gallery_type == 'post') echo "checked=1";?>> Only Posts.<br/> <input type="radio" name="gallery_type" value="gallery" <?php if ($gallery_type == 'gallery') echo "checked=1";?>> Only Galleries.<br/> <?php } ?>
Lines 6-7 – Get previously saved gallery type data (if any). If none, then use attachment as the default gallery type.
Line 9 – Add hidden security nonce key.
Lines 10-13 – Render the appropriate radio buttons, and check the one that was previously selected.
This renders a new custom metabox in our Gallery screen –
We can use this method to render any type of HTML form that we want for our custom post type interface.
However, we are not done yet. add_meta_box only adds the input controls; we must still attach and save the user data to our gallery object. This is achieved using the save_post action hook.
// Add to admin_init function add_action('save_post', array(&$this,'save_gallery_data') ); function save_gallery_data($post_id) { // verify this came from the our screen and with proper authorization. if ( !wp_verify_nonce( $_POST['gallery_type_noncename'], 'gallery_type'.$post_id )) { return $post_id; } // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want to do anything if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id; // Check permissions if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id; // OK, we're authenticated: we need to find and save the data $post = get_post($post_id); if ($post->post_type == 'gallery') { update_post_meta($post_id, '_gallery_type', esc_attr($_POST['gallery_type']) ); return(esc_attr($_POST['gallery_type'])); } return $post_id; }
[This function was adapted from the add_meta_box example in the WordPress Codex]
Lines 6-8 – Verify that the form came from our gallery type metabox, and our gallery custom post type screen.
Lines 11-12 – We don’t need to save the data if it is just an autosave event.
Lines 15-16 – Only save the data if the user has proper permissions to edit the given post object.
Lines 20-24 – Save the gallery type custom metabox data.
We Are Done!
If you want to include specialized metaboxes from plugins or themes, you will need to edit the plugin file and look for the relevant add_meta_box and save_post hooks. Then, just include them in your own admin_init function.
Make sure to use your own custom post type name (argument 4) when issuing the add_metabox command.
jamie says
this would have been a great tut had you not left out the part about retrieving the information from the database. How do I get the values from the radio buttons?
ShibaShake says
I am not sure I understand your question.
In the save_gallery_data function, values from the radio buttons ($_POST[‘gallery_type’]) are retrieved and stored (line 22).
Erik says
I’ve made a blank example for custom meta boxes on posts, and give explanation on how to insert them into custom post types as well here. I’d love to know what you think.
ShibaShake says
Good tutorial, I like it!
sebouille says
Hi
How i can restrict meta box category with arg child-of ?
I created a plugin with
add_action(‘load-post.php’, array(‘Myplugin’,’loadpost’));
And
function loadpost() {
remove_meta_box(‘categorydiv’, ‘post’, ‘normal’);
add_meta_box(‘categorydiv’, _(‘Category’), ‘post_categories_meta_box’, ‘post’, ‘side’, ‘core’, array( ‘taxonomy’ => ‘category’, ‘child_of’ => 80));
}
Have any idea ?
Thanks for great blog
sebouille says
I find with this function
wp_terms_checklist($post->ID, array( ‘taxonomy’ => $taxonomy, ‘descendants_and_self’ => $wp_cat_id_mother, ‘selected_cats’ => $idCatSelected ) )
So
1) remove_meta_box(‘categorydiv’, ‘post’, ‘normal’);
2) add_meta_box(‘categorydiv1’, _(‘Categories’), array( ‘MyPluginClass’, ‘display_restrict_category’), ‘post’, ‘side’, ‘core’);
3)
function display_restrict_category( ) {
…
wp_terms_checklist($post->ID, array( ‘taxonomy’ => $taxonomy, ‘descendants_and_self’ => $wp_cat_id_mother, ‘selected_cats’ => $idCatSelected ) )
…
}
Thanks
Frank Perez says
Here’s a good plugin that handles all the custom metaboxes for you as well as custom post types. http://wordpress.org/extend/plugins/custom-metaboxes/
Alex says
SOLVED IT !!!
Its necesary to add this action
add_action(‘admin_menu’, ‘architecture_admin_menu’);
Jacob says
Where do you add the action? beginning or end of the code?
Would be great to see the code in full!
-J
ShibaShake says
I usually add the admin_menu hook at the beginning of my theme functions.php file or at the beginning of my main plugin file. I put it together with the init and admin_init hooks. When I use class wrappers, I put it within the class constructor function. If you want to look at an example plugin with these function calls then check out the Shiba Example plugin.
The register_post_type function call I execute from my init function.
Both the Shiba Media Library plugin and Shiba Custom Background plugin use custom post type metaboxes. Full working code can be found there but the plugins also contain a whole bunch of other stuff.
Alex says
Ey men! your last posts about custom post types are amazing!! I just created my first custom type, but when trying to add a meta box gives me this error.
Fatal error: Call to undefined function add_meta_box() in /home/xxx/public_html/wp-content/themes/xxx/custom-types.php on line 43
custom-types is an include in functions.php
I am using wordpress 3.0
This is the code in custom-types.php
Please! help, wp is correctly updated to 3.0, i can find the function add_meta_box and cant find why this happens!
++Thanks++
Andrew says
FYI, this part is not “out of the box” so you have to wrap it into a function and use add_action such as
add_action( 'admin_init', 'news_meta_boxes', 1 );
// Add meta box goes into our admin_init function
function news_meta_boxes() {
add_meta_box('gallery-type-div', __('Gallery Type'), 'gallery_type_metabox', 'news', 'normal', 'high');
}
This also lets you add all your meta boxes in one add_action as referenced in the codex at http://codex.wordpress.org/Function_Reference/add_meta_box
Ben Palmer says
Thanks very much, i’ve been searching for how to do meta box stuff on the new custom post types and this article has finally helped me to understand.
Darren says
Thanks for this, very useful!
I created a checkbox to flag featured “Best Practices” on a site I am putting together. Perhaps this will be helpful to your readers:
ShibaShake says
Examples like these are always very useful. Thanks for sharing it with us Darren.
Matt says
Oh, my gosh, thank you thank you thank you. I have been dealing with this stupid nonce thing looking for help. I stumbled onto your site and this method works great. Thank you so much!