I would like to group posts of a custom post type based on tags, but the default functionality does not do for the project I am working on.

I want the user to be able to select only one tag, not multiple tags, from a list of all the tags entered for that custom post type (drop down or radio buttons).

The user can create as many tags as he wants from the page for adding a custom taxonomy, and all these tags will be listed in the meta box on the single custom post page.

Any suggestion?

4 Answers 4


In my last project i had the same issue and i just used this:

first get the list of tags to a var using the get_categories function by passing the right taxonomy like this:

    $args = array(

    'orderby'                  => 'name',
    'order'                    => 'ASC',
    'hide_empty'               => 0,
    'taxonomy'                 => 'post_tag'
    foreach($categories as $category) { 
    $tags[] =  $category->name ;  

then create the arguments for the meta box

$prefix = 'CPT_my_meta';
$meta_box = array(
    'id' => 'custom-meta-box',
    'title' => 'tags',
    'page' => 'CPT name',
    'context' => 'normal',
    'priority' => 'high',
    'fields' => array(
            'name' => 'tags',
            'desc' => 'select a tag',
            'id' => $prefix . 'name',
            'type' => 'select',
            'options' => $tags

then add the meta box

add_action('admin_menu', 'add_my_box');

// Add meta box
function add_my_box() {
    global $meta_box;

    add_meta_box($meta_box['id'], $meta_box['title'], 'metabox_callback', $meta_box['page'], $meta_box['context'], $meta_box['priority']);

then all you have to do is create a function to show the meta box

//show meta box
function metabox_callback(){
global $meta_box, $post;

    // Use nonce for verification
    echo '<input type="hidden" name="META_BOX_NONEC" value="', wp_create_nonce(basename(__FILE__)), '" />';

    echo '<table class="form-table">';

    foreach ($meta_box['fields'] as $field) {
        // get current post meta data
        $meta = get_post_meta($post->ID, $field['id'], true);

        echo '<tr>',
                '<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>',
        switch ($field['type']) {
            case 'select':
                echo '<select name="', $field['id'], '" id="', $field['id'], '">';
                foreach ($field['options'] as $option) {
                    echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
                echo '</select>';
        echo    '</td></tr>';
    echo '</table>';

and save it on post save

//hook save function
add_action('save_post', 'save_my_meta_box');

// Save data from meta box
function save_my_meta_box($post_id) {
    global $meta_box;

    // verify nonce
    if (!wp_verify_nonce($_POST['META_BOX_NONEC'], basename(__FILE__))) {
        return $post_id;

    // check autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return $post_id;

    // check permissions
    if ('page' == $_POST['post_type']) {
        if (!current_user_can('edit_page', $post_id)) {
            return $post_id;
    } elseif (!current_user_can('edit_post', $post_id)) {
        return $post_id;

    foreach ($meta_box['fields'] as $field) {
        $old = get_post_meta($post_id, $field['id'], true);
        $new = $_POST[$field['id']];

        if ($new && $new != $old) {
            update_post_meta($post_id, $field['id'], $new);
        } elseif ('' == $new && $old) {
            delete_post_meta($post_id, $field['id'], $old);

hope this helps

  • This is awesome! Thank you very much! I will give it a try immediately ;) Jan 21, 2011 at 10:02
  • There are metabox actions available specifically so you can hook on and add metaboxes, so i'm wondering why you're using admin_menu, some appropriate actions would be add_meta_boxes, add_meta_boxes-%POST_TYPE%, and do_meta_boxes..
    – t31os
    Jan 21, 2011 at 14:51
  • you are 100% right!
    – Bainternet
    Jan 21, 2011 at 16:05
  • I guess the problem is in the registration of my custom taxonomy...it is not registered yet when get_categories is called.... Jan 21, 2011 at 16:11
  • I am pretty sure that this code does not save the selected values as a taxonomy, but instead it does so as a custom field. So it uses the list of terms from a given taxonomy, but then saves the selected term as a custom field and retrieve that custom field.
    – Didier A.
    Feb 5, 2012 at 3:21

I tried to show the list and it does work if you use post_tag or category, but it gives me the list of the default post type tags or categories.

I want to have the list of the custom taxonomies for my custom posts. My custom post type is "au-gallery" and my custom taxonomy is "gallery" therefore I tried

$args = array( 'type' => 'au-gallery', 'orderby' => 'name', 'order' => 'ASC', 'hide_empty' => 0, 'taxonomy' => 'gallery' );

but I got only an empty list.

I had a look at get_the_term_list and get_the_terms but those functions requires the post ID so...do I need to run a loop for al my custom posts to get this list or is there a better way??

  • Try get_terms( 'taxonomyNAMEhere', $args ).. where $args is an array of the appropriate arguments, see: codex.wordpress.org/Function_Reference/get_terms
    – t31os
    Jan 21, 2011 at 14:53
  • I tried, but again it does not work with custom taxonomies Jan 21, 2011 at 15:32
  • Actually, taxonomy_exists('gallery') gives false, but everything is fine in my admin panel...I can see my custom taxonomies and add/edit them Jan 21, 2011 at 15:55
  • remove 'type' => 'au-gallery', from your args array, and you\ll be fine
    – Bainternet
    Jan 21, 2011 at 16:09
  • I tried but it does not make any difference. Jan 21, 2011 at 16:59

For custom taxonomies, I found a solution without writing a save_post hook. When register a taxonomy, need to specify 'meta_box_cb' => 'single_taxonomy_select_meta_box'

For more details, please download this gist

 * Meta box to select only one taxonomy value
 * @param WP_Post $post
 * @param array   $box
function single_taxonomy_select_meta_box( WP_Post $post, Array $box ) {

$taxonomy = $box['args']['taxonomy'];

$term_name_of_the_current_post = wp_get_object_terms( $post->ID, $taxonomy, [ 'fields' => 'names' ] )[0];

$all_term_names = get_terms( $taxonomy, [ 'fields' => 'names', 'hide_empty' => false ] );
    <?php esc_html_e( 'Please choose:' ); ?>
    <select name="tax_input[<?php echo esc_attr( $taxonomy ); ?>]">
        <?php foreach ( $all_term_names as $term_name ) : ?>
            <option <?php selected( $term_name_of_the_current_post, $term_name ); ?>>
                <?php echo esc_html( $term_name ); ?>
        <?php endforeach; ?>


If you want to show all the tags in the select box dropdown and also want to select the current tag should be on top in the select box
And also you will move to the tag page while selecting the tag from the select box

<select name="tags" id="tags" onchange="location = this.value;">

$tags = get_tags();
$query = new WP_Term_Query(array(
    'object_ids' =>  get_the_ID(),
    'fields'     => 'ids',

$tag_id = get_queried_object()->term_id;
if ( $tags ) {
    foreach ( $tags as $tag ) {
        $selected= ( $tag->term_id == $tag_id )?'selected':'';
        printf('<option %1$s value="%2$s">%3$s</option>',
            get_tag_link( $tag->term_id ),


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.