最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

loop - have_posts() return false but count says "3"

programmeradmin6浏览0评论

The situation is this: I have created a custom post type which works perfectly, now I want to create a specific archive page template for the taxonomies of this post type.

I duplicated the archive.php page of my theme (schema by MTS) but it doesn't work in this case.

Here the code:

<?php

$term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ), get_query_var( 'count' ) );
echo $term->name;
echo ' has nr elements: ';
echo $term->count;


?>
<div id="page">
    <div class="<?php mts_article_class(); ?>">
        <div id="content_box">
            <h1 class="postsby">
                <span><?php echo the_archive_title(); ?></span>
            </h1>
            <?php $j = 0; if (have_posts()) : while (have_posts()) : the_post(); ?>
                <article class="latestPost excerpt  <?php echo (++$j % 3 == 0) ? 'last' : ''; ?>">
                    <?php mts_archive_post(); ?>
                </article><!--.post excerpt-->
                <?php endwhile; else: echo 'nothing'; endif; ?>

            <?php if ( $j !== 0 ) { // No pagination if there is no posts ?>
                <?php mts_pagination(); ?>
            <?php } ?>
        </div>
    </div>
    <?php get_sidebar(); ?>
<?php get_footer(); ?>

The strange aspect is that the code print "nothing" because the function have_posts() return false but the $term->count is 3.

Can you help me please? Thank you very much in advance!

The situation is this: I have created a custom post type which works perfectly, now I want to create a specific archive page template for the taxonomies of this post type.

I duplicated the archive.php page of my theme (schema by MTS) but it doesn't work in this case.

Here the code:

<?php

$term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ), get_query_var( 'count' ) );
echo $term->name;
echo ' has nr elements: ';
echo $term->count;


?>
<div id="page">
    <div class="<?php mts_article_class(); ?>">
        <div id="content_box">
            <h1 class="postsby">
                <span><?php echo the_archive_title(); ?></span>
            </h1>
            <?php $j = 0; if (have_posts()) : while (have_posts()) : the_post(); ?>
                <article class="latestPost excerpt  <?php echo (++$j % 3 == 0) ? 'last' : ''; ?>">
                    <?php mts_archive_post(); ?>
                </article><!--.post excerpt-->
                <?php endwhile; else: echo 'nothing'; endif; ?>

            <?php if ( $j !== 0 ) { // No pagination if there is no posts ?>
                <?php mts_pagination(); ?>
            <?php } ?>
        </div>
    </div>
    <?php get_sidebar(); ?>
<?php get_footer(); ?>

The strange aspect is that the code print "nothing" because the function have_posts() return false but the $term->count is 3.

Can you help me please? Thank you very much in advance!

Share Improve this question edited Sep 24, 2017 at 11:59 Johansson 15.4k11 gold badges43 silver badges79 bronze badges asked Apr 9, 2016 at 20:05 castpcastp 212 bronze badges 3
  • what is your 4th parameter on get_term_by ? – Jevuska Commented Apr 10, 2016 at 6:53
  • Do a var_dump( $wp_query ); and inspect the main query object – Pieter Goosen Commented Apr 10, 2016 at 7:23
  • @Jevuska I used 'count' to get the number of element with that slug, is it wrong used in this way? @ Pieter I answered you below :-) – castp Commented Apr 10, 2016 at 8:21
Add a comment  | 

3 Answers 3

Reset to default 1

I had same problem.

According to documentation:

The hierarchy for a custom taxonomy is listed below:

taxonomy-{taxonomy}-{term}.php
taxonomy-{taxonomy}.php
taxonomy.php
archive.php
index.php

So, it doesn't matter witch template file you are using, all of them will generate same issue.

When I put in the beginning of template file code var_dump($wp_query);, i found this:

public 'request' => string 'SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1  AND ( 
  wp_term_relationships.term_taxonomy_id IN (20)
) AND wp_posts.post_type IN ('post', 'page', 'attachment') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 10' (length=433)
  public 'posts' =>

Important part in this query is wp_posts.post_type IN ('post', 'page', 'attachment').

Problem occur because there is no your custom post_type in this array ('post', 'page', 'attachment').

I don't know why it's happen, but it's possible to fix it using pre_get_posts hook:

add_filter('pre_get_posts', 'add_custom_post_type_to_query');
function add_custom_post_type_to_query($query) {
    // We do not want unintended consequences.
    if ( is_admin() || ! $query->is_main_query() ) {
        return;    
    }

    // Check if custom taxonomy is being viewed
    if( is_tax() && empty( $query->query_vars['suppress_filters'] ) )         
    {
        $query->set( 'post_type', array( 
            'post',
            'page',
            'my_custom_post_type'
        ) );
    }
}

Same issue as the OP. As @sviriden noted in his answer, the problem is that the main query is not including your custom post type in the wp_posts.post_type IN clause. I tracked down the issue in class-wp-query.php to these lines:

    if ( 'any' == $post_type ) {
        $in_search_post_types = get_post_types( array( 'exclude_from_search' => false ) );
        if ( empty( $in_search_post_types ) ) {
            $where .= ' AND 1=0 ';
        } else {
            $where .= " AND {$wpdb->posts}.post_type IN ('" . join( "', '", array_map( 'esc_sql', $in_search_post_types ) ) . "')";
        }
    } elseif ( ! empty( $post_type ) && is_array( $post_type ) ) {
        $where .= " AND {$wpdb->posts}.post_type IN ('" . join( "', '", esc_sql( $post_type ) ) . "')";
    } elseif ( ! empty( $post_type ) ) {
        $where           .= $wpdb->prepare( " AND {$wpdb->posts}.post_type = %s", $post_type );
        $post_type_object = get_post_type_object( $post_type );
    } elseif ( $this->is_attachment ) {
        $where           .= " AND {$wpdb->posts}.post_type = 'attachment'";
        $post_type_object = get_post_type_object( 'attachment' );
    } elseif ( $this->is_page ) {
        $where           .= " AND {$wpdb->posts}.post_type = 'page'";
        $post_type_object = get_post_type_object( 'page' );
    } else {
        $where           .= " AND {$wpdb->posts}.post_type = 'post'";
        $post_type_object = get_post_type_object( 'post' );
    }

The key is the $in_search_post_types which only includes Custom Post Types that have exclude_from_search as false. In my case I had exclude_from_search as true when registering the custom post type. Changing this value to false resolved the issue.

What is wrong here is your assumptions that the values should be the same. I don't know of the top of my head what exactly the term count represent, and it is not apparent from the docs, but it is most likely a raw number of posts associated with the term. OTOH wp_query (which is used for the main loop) takes into account user permissions on top of that raw number, simplest example - by default the result will not include posts which are not published, more complex things can happen if you have some plugins which manipulate the query.

发布评论

评论列表(0)

  1. 暂无评论