Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm trying to include a WP_Query in a save_post function for a custom post type. The query is used to check all the other posts for a custom field bh_shortcode to make sure the content of the field is not duplicated.

However, when I create and loop through the wp_query, the value of $post changes, and one of the post entires that appears in the results of the wp_query is then set to $post, and as a result, all the fields are then saved to the wrong post (rather than the one I have open).

The wp_reset_query() doesn't appear to have any effect.

How can I correct this?

function save_bhour_details(){
    global $post;

    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
        return;
    }

    if ( get_post_type($post) != 'bhours'){
        return;
    }

    //validate shortcode
    $bh_shortcode='';
    $error_shortcode_empty=false;
    $error_shortcode_duplicate=false;


    if(isset($_POST['bh_shortcode']) && !empty($_POST['bh_shortcode'])){
        $bh_shortcode=bh_strip_special_chars($_POST['bh_shortcode']);

        if(empty($bh_shortcode)){
            $error_shortcode_empty=true;
        }
        else{

            $query_validate = new WP_Query(array(
                'post_type'=>'bhours',
            ));

            while($query_validate->have_posts()){
                $query_validate->the_post();
                $bh_post_shortcode=array_shift(get_post_custom_values('bh_shortcode'));

                if($bh_post_shortcode==$bh_shortcode){
                    $error_shortcode_duplicate=true;
                    break;
                }
            }
            wp_reset_query();           
        }

    }
    else{
        $error_shortcode_empty=true;
    }

    if(!$error_shortcode_empty && !$error_shortcode_duplicate){
        update_post_meta($post->ID, 'bh_shortcode', $bh_shortcode);
    }
    else{
        update_post_meta($post->ID, 'bh_shortcode', '');
    }

}
add_action('save_post', 'save_bhour_details');
share|improve this question

1 Answer 1

up vote 2 down vote accepted

Since wp_reset_query() and wp_reset_post() didn't appear to do anything in this situation, here's something that seems to work. I'm not entirely sure if this is the accepted approach, but I got it working by temporarily storing the $post value before the WP_Query, then setting it back to the $post variable after the query was complete.

$currentpost = $post;

$query = new WP_Query(/* ... */);

while($query->have_posts()){
     $query->the_post();
     //do stuff
}

$post = $currentpost;
share|improve this answer
    
wp_reset_post() won't work because it resets the global $post to whatever is stored in the $wp_query. On save_post, WordPress doesn't use store the post beings saved in side $wp_query (in fact its not using it all). Thus when you 'reset' the post, you are probably resetting it to the first post in your query. –  Stephen Harris Sep 5 '12 at 22:10
    
For your use case, I would use get_posts() and pass the post ID where needed - and not touch the global $post. This would actually be more efficient too. –  Stephen Harris Sep 5 '12 at 22:11
    
@StephenHarris how would I retrieve the post ID withing the have_posts() while loop without touching $post? –  Force Flow Sep 5 '12 at 22:47
2  
Each object in the array returned by get_posts() has the property ID. E.g. foreach( get_posts() as $bhour){ echo $bhour->ID;} –  Stephen Harris Sep 5 '12 at 23:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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