I'm not sure why this is not working as its a very simple query. It works when i pull all posts including pending, but not when i want to get posts that are only published.

I have a function to get posts. I pass in a bool variable. If its true, i want to pull all posts from a custom post type called books, including ones that are pending/draft. If false i only want the published posts. I see no issues with the code, but it wont work.

$args = array( 
    'post_type' => 'book',
    'showposts' => -1,
    'tax_query' =>  array('relation' => 'AND',
        array( 'taxonomy' => 'book-category', 'field' => 'term_id', 'terms' => $termid)
    'orderby' => 'date',
    'order' => 'ASC'

if($getpending == true) $args["post_status"] = "any";
else $args["post_status"] = "publish";

$posts = query_posts($args);
  • 1
    query_posts modifies WordPress' main loop and is unsuited for pretty much every purpose (wordpress.stackexchange.com/questions/1753/…). There are numerous reasons why query_posts wouldn't work as expected in this case. Have you tried using get_posts instead?
    – engelen
    Mar 26, 2016 at 9:13
  • this worked. if you want to make this an answer ill give you the vote Mar 26, 2016 at 9:16
  • Glad to hear that it worked! Done.
    – engelen
    Mar 26, 2016 at 9:21
  • By the way, if the answer works, you should accept the answer so it doesn't show up as unanswered anymore and people know where to find the working answer.
    – engelen
    Mar 27, 2016 at 16:09

3 Answers 3


First off, you probably shouldn't be using query_posts, which modifies WordPress' main loop and is unsuited for pretty much any purpose (read When should you use WP_Query vs query_posts() vs get_posts()? for more info). There are numerous reasons why query_posts wouldn't work as expected in this case.

WordPress has two proper approaches to fetching posts: the WP_Query object and the get_posts function. They work very similarly, with get_posts using WP_Query internally. However, as one would expect, WP_Query allows for more control.

For your case, get_posts should work (as there is no further flaw in the code you posted).


Apart from the use of query_posts, you have another issue, and that is the local use of global $posts variable. $posts is the global used to hold the main query's posts array. Never use global variables as local variables. Changing global variables is really bad as you break their original and intended values, which is really hard to debug. Instead of using $posts, use a custom variable like $posts_array.

You most probably also do not need the custom query, but if you do, use WP_Query or get_posts(), never use query_posts. I have discussed everything in detail in this post which also linked to a couple of very important posts.

Just to quickly touch on few other points:

  • You should really work on your code's indentation and separation. Your code is a bit hard to read and to debug when you cram so many things into one long line.

  • You should be careful setting post_status to any as this will expose private posts to non logged in users, it will also show future posts which is not published yet. This might also expose custom statuses that you would not want to show. Rather explicitly set the post statuses you need.

    From query.php

    if ( in_array( 'any', $q_status ) ) {
        foreach ( get_post_stati( array( 'exclude_from_search' => true ) ) as $status ) {
            if ( ! in_array( $status, $q_status ) ) {
                $e_status[] = "$wpdb->posts.post_status <> '$status'";
    } else {

    Note: 'exclude_from_search' => true means only trash and auto-draft are excluded from any

  • showposts have been dropped in favor of posts_per_page. It is not depreciated, but if used, it gets converted into posts_per_page, so why not use posts_per_page from the start

    if ( isset($q['showposts']) && $q['showposts'] ) {
        $q['showposts'] = (int) $q['showposts'];
        $q['posts_per_page'] = $q['showposts'];
  • You don't need to set arguments to their default values. You can simply leave that out and save extra space and time

If this is a secondary query, you can probably look at something like the following: (Requires PHP 5.4+)

$args = [
    'post_type'      => 'book',
    'posts_per_page' => -1,
    'order'          => 'ASC'
    'tax_query'      =>  [
            'taxonomy' => 'book-category', 
            'terms'    => $termid

if ( true == $getpending ) {
    if ( is_user_logged_in() ) { // This can be adjusted to match core
        $args["post_status"] = ['publish', 'private', 'draft'];
    } else {
        $args["post_status"] = ['publish', 'draft'];

$posts_array = WP_Query( $args );

I do believe, looking at the terms value in you tax_query, this might be the main query. If so, you should really look into pre_get_posts to alter the main query


Try using a custom query instead https://codex.wordpress.org/Class_Reference/WP_Query as using query_posts() https://codex.wordpress.org/Function_Reference/query_posts isn't meant to be used by plugins or themes.

Replace your code with this one:

$args = array( 
        'post_type' => 'book',
        'posts_per_page' => -1,
        'tax_query' =>  array(
                                'relation' => 'AND',
                                array( 'taxonomy' => 'book-category', 
                                        'field' => 'term_id', 
                                        'terms' => $termid
        'orderby' => 'date',
        'order' => 'ASC'

    if($getpending == true) 
        $args["post_status"] = "any";
        $args["post_status"] = "publish";

    $ustom_posts = new WP_Query($args);

            //echo $post->post_title;   
            //your further code

Your Answer

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

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