Unable to save custom taxonomy terms in a custom-built metabox

I’ve roughly followed the tutorial here on how to create “custom taxonomy input panels”. I’m using a custom post type of homes and a custom taxonomy called beds (used to record the number of beds in a house). I’ve got the taxonomy terms showing up in a drop down menu, but cannot get them to save when the post is saved. I started to just post the code that is intended to save the term, but realized that I should post the code that creates and displays the metabox as well, for context. The custom post type name is ‘homes’ and the custom taxonomy name is ‘beds’. The taxonomy is hierarchical (not that I think that matters in this case, but I could be wrong).

//adding metaboxes for the homes post type
function add_homes_metaboxes() {
    add_meta_box( 'blackstone_homes_beds', 'Beds', 'blackstone_homes_beds', 'homes', 'side', 'default' );
}

function add_homes_menus() {
    if ( !is_admin() )
        return;
    add_action( 'admin_menu', 'add_homes_metaboxes' );
    /* Use the save_post action to save new post data */
    add_action( 'save_post', 'save_taxonomy_data' );
}

add_homes_menus();

function blackstone_homes_beds( $post ) {

    echo '<input type="hidden" name="beds_noncename" id="beds_noncename" value="' .
    wp_create_nonce( 'taxonomy_beds' ) . '" />';

    // Get all theme taxonomy terms
    $beds = get_terms( 'beds', 'hide_empty=0' );
    $stuff = array( 'this', 'that' );
    //print_r($beds);
?>
<select name='homes_beds' id='homes_beds'>
    <!-- Display beds as options -->
<?php
    $names = wp_get_object_terms( $post->ID, 'beds' );
?>
    <option class='beds-option' value=''
            <?php if ( !count( $names ) )
                echo "selected"; ?>>None</option>
            <?php
            foreach ( $beds as $bed ) {
                if ( !is_wp_error( $names ) && !empty( $names ) && !strcmp( $bed->slug, $names[0]->slug ) )
                    echo "<option class='beds-option' value='" . $bed->slug . "' selected>" . $bed->name . "</option>n";
                else
                    echo "<option class='beds-option' value='" . $bed->slug . "'>" . $bed->name . "</option>n";
            }
            ?>
            </select>
<?php
        }

        function save_taxonomy_data( $post_id ) {
// verify this came from our screen and with proper authorization.

            if ( !wp_verify_nonce( $_POST['beds_noncename'], 'taxonomy_beds' ) ) {
                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 ( 'homes' == $_POST['post_type'] ) {
                if ( !current_user_can( 'edit_page', $post_id ) )
                    return $post_id;
            } else {
                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 == 'homes'){
                $beds = $_POST['homes_beds'];
                wp_set_object_terms( $post_id, $beds, 'beds' );
            }
            return $beds;
        }

I know there’s another very similar question here already, but the solution to it uses the WPAlchemy class, and I’d rather not do so.

Read More

Any suggestions on what I might have wrong? I’ve been staring at this all day, so I fully expect to find out I’ve just got a variable name off by one character or something.

EDIT: Here’s what I changed to get it working correctly:

Instead of echoing the hidden field with the nonce, I used wp_nonce_field( __FILE__, 'taxonomy_beds' ); and when verifying the nonce, I used if ( !wp_verify_nonce( $_POST['taxonomy_beds'], __FILE__ ) )

Related posts

Leave a Reply

2 comments

  1. I believe your problem might be nonce-related. I see you’re doing what I did at one point with a problem I had when I tried doing nonces the way you’re using them.

    I’ll quote @EAMann on this:

    The standard way to create this field
    is using WordPress’ wp_nonce_field()
    function. It will add the hidden
    field for you:

    wp_nonce_field( __FILE__, 'argus_edit_visitor' );
    

    Try that, see if it works. I don’t see anything else wrong with your code.

    If that doesn’t work, try print_r( $_POST['beds'] ) to reveal what is being submitted in $_POST['beds'].