WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have the following issue:

I am creating a custom-meta-box for the user to add custom fields in a friendly way.
I want to generate a drop-down box with all posts that fall under category 10.
I have created a loop inside the functions file for retrieving the posts I want and to create a dropdown select list.

So when I go to admin -> posts and select a post to edit, I get the following issue:
the last post will load no matter which one I select.

Here is the code used inside the functions file and then called when generating the html code for the custom meta-box:

function get_project_ids($proj_cat = 10) {

$output = '';

$catt = get_categories('parent='.$proj_cat.'&hide_empty=0');

    foreach ($catt as $c) :

        $output .= '<optgroup label="'.$c->name.'">';
        $d = get_categories('parent='.$c->cat_ID.'&hide_empty=0');

            foreach ($d as $e) :
            $output .= '<optgroup label="'.$e->name.'">';

                $args = array( 'nopaging' => true, 'cat' => $e->cat_ID );
                $project_query = new WP_Query( $args );

                    while ( $wp_query->have_posts() ) : $wp_query->the_post();
                        $project_id = (get_post_meta($post->ID, 'project_code', true) != "")?get_post_meta($post->ID, 'project_code', true):"";
                        $output .= '<option value="'.$post->ID.'">'.$project_id.'-'.get_the_title().'</option>';    

                $wp_query = null;
                $wp_query = $original_query;

            $output .= '</optgroup> <!-- END level-b -->';

        $output .= '</optgroup> <!-- END level-a -->';

return $output;
share|improve this question
Where does $e come from? Second: Where's the original $output you're .= adding too? Third: Why are you setting $wp_query to null? No reason to do that. – kaiser Jul 3 '11 at 21:28
ok you're right I should be more clear. (i) $e comes from a foreach loop and is the id of the category (ii) $output is initialized a few lines back. (iii) I'm actually following an example from codex where the original wp query is temporary put aside. ... The thing is that this query for some reason forces the same post in the admin edit post page. – ion Jul 3 '11 at 23:44
Could you please simply post your whole code? And then add the information to your Q? Hint: You can edit your Q. Hint #2: You have a "help" link for commenting and such that will you show you the mark-up stuff like code in comments and else. Thanks. – kaiser Jul 4 '11 at 1:51

I am not sure about the issue, but my advice would be to try and refactor this to use get_posts() and template tags that can work without $post global variable. Basically do not touch globals at all.

Loops in front-end are almost civilized nowadays, but internals of admin are still very wild. :)

share|improve this answer
Great man!!!! It worked ... I will edit my original post with the working code – ion Jul 4 '11 at 11:11
@ion it is more proper to add working solutions as new answer (even for own question), that is how site is supposed to work – Rarst Jul 4 '11 at 11:24

You're creating a new query, called $project_query, then never using it.

Then you're using $wp_query, for which there is no global $wp_query; statement.

Then you're assigning null to $wp_query then assigning the value of an undefined variable to it.

Instead remove the two unnecessary lines and use $project_query instead. here's the modified query loop:

            $args = array( 'nopaging' => true, 'cat' => $e->cat_ID );
            $project_query = new WP_Query( $args );

                while ( $project_query ->have_posts() ) : $project_query ->the_post();
                    $project_id = (get_post_meta($post->ID, 'project_code', true) != "")?get_post_meta($post->ID, 'project_code', true):"";
                    $output .= '<option value="'.$post->ID.'">'.$project_id.'-'.get_the_title().'</option>';    

share|improve this answer
I was unable to get this to work properly. It would still overwrite the post slug / excerpt (when editing a post). – cale_b Oct 20 '15 at 19:54
That's an entirely new and separate problem, you shouldn't be setting input names that clash with ones already used by core – Tom J Nowell Oct 21 '15 at 6:03
how is that a separate problem? And can you help me see / understand what I'm doing to "set input names that clash with ones used by core"? – cale_b Oct 21 '15 at 14:04
You should ask a new question – Tom J Nowell Oct 21 '15 at 22:25

This is the working code:

global $post;
$tmp_post = $post;
$args = array( 'numberposts' => 10000, 'category' => $e->cat_ID );
$myposts = get_posts( $args );
foreach( $myposts as $post ) : setup_postdata($post);
    $project_id = (get_post_meta($post->ID, 'project_code', true) != "")?get_post_meta($post->ID, 'project_code', true):"";
    $output .= '<option value="'.$post->ID.'">'.$project_id.'-'.get_the_title().'</option>';    
$post = $tmp_post;
share|improve this answer
Mark your question as answered. – toscho Feb 14 '12 at 11:52
Can someone advise why $tmp_post = $post; is being added before the foreach statement and $post = $tmp_post; is being added after it. Without this it doesn't work and I am not advanced enough to figure out why this is being done and how it is solving things :) – Matt Royal Sep 8 '15 at 12:06

Found this question, reviewed the answers, but had to do a combination because I wanted to use the WP_Query, AND was still having issues in the admin dashboard.

This code works properly for me in a metabox when editing posts:

function custom_metabox() {
    global $post;
    $temp_post = $post;

    $args = array(
        'post_type'  => 'custom_post_type',
        'meta_key'   => '_custom_meta_key',
        'meta_value' => TRUE

    $custom = new WP_Query( $args );

    if ( $custom->have_posts() ) {
        while ( $custom->have_posts() ) {
            // ... with access to the data with functions like get_the_ID(), get_the_title(), etc.


    $post = $temp_post;

    // ... the rest of my metabox ...

NOTE: Without the global $post, $temp_post = $post and $post = $temp_post, I was still having issues with the slug and the excerpt getting overwritten. By adding those bits of code, this seems to be working solidly now.

share|improve this answer
This is the purpose of the wp_reset_postdata call, you should call it inside the if statement so that it only resets the post data when necessary. Your current code resets the postdata even when it hasn't changed – Tom J Nowell Oct 21 '15 at 6:02
@TomJNowell - Good point. I've edited the answer. – cale_b Oct 21 '15 at 14:01

Your Answer


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.