Using the loop inside admin

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.

Read More

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>';    
                    endwhile; 

                wp_reset_postdata();
                $wp_query = null;
                $wp_query = $original_query;

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

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

return $output;

Related posts

Leave a Reply

4 comments

  1. 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. 🙂

  2. 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>';    
                    endwhile; 
    
                wp_reset_postdata();
    
  3. 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>';    
    endforeach;
    $post = $tmp_post;
    
  4. 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() ) {
                $custom->the_post();
                // ... with access to the data with functions like get_the_ID(), get_the_title(), etc.
            }
    
            wp_reset_postdata();
        }
    
        $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.