我正在使用pre_get_posts来调整首页上显示的帖子数。

function lifelounge_query_adjust( $query ) {
    if ( is_home() ) {
        set_query_var( 'posts_per_page', 12 );
        return;
    }
}
add_filter( 'pre_get_posts', 'lifelounge_query_adjust' );


但是我遇到了粘帖问题。基本上,如果我有任何粘性帖子,查询将显示比我指定的12个帖子更多的内容,因为它将显示12个加上任何粘性帖子。我当然可以忽略粘性帖子:

function lifelounge_query_adjust( $query ) {
    if ( is_home() ) {
        set_query_var( 'posts_per_page', 1 );
        set_query_var( 'ignore_sticky_posts', 1 );
        return;
    }
}
add_filter( 'pre_get_posts', 'lifelounge_query_adjust' );


但是我认为这不是理想的选择。我认为粘性帖子应包含在12个帖子的限制中,而不应添加到该限制中。那对我来说最有意义。有办法实现吗?我是否犯了一个值得当面使用的错误?

几乎重复了以下内容:粘性帖子和每页帖子,但是由于本地化而被怪异地关闭了。我不同意,显然是因为我在寻找答案,也因为这是一个问题,为什么如果您使用粘性帖子,WordPress似乎不尊重posts_per_page的限制。如果您希望每页12个帖子,那么您应该得到12个而不是13个,这是您只有一个粘性帖子时所得到的结果。

#1 楼

这是一种通过获取粘性帖子数(如果有)来解决粘性帖子的方法,并将其包括在计算posts_per_page参数中:

add_action('pre_get_posts', 'ad_custom_query');
function ad_custom_query($query) {

    if ($query->is_main_query() && is_home()) {

        // set the number of posts per page
        $posts_per_page = 12;
        // get sticky posts array
        $sticky_posts = get_option( 'sticky_posts' );

        // if we have any sticky posts and we are at the first page
        if (is_array($sticky_posts) && !$query->is_paged()) {

            // counnt the number of sticky posts
            $sticky_count = count($sticky_posts);

            // and if the number of sticky posts is less than
            // the number we want to set:
            if ($sticky_count < $posts_per_page) {
                $query->set('posts_per_page', $posts_per_page - $sticky_count);

            // if the number of sticky posts is greater than or equal
            // the number of pages we want to set:
            } else {
                $query->set('posts_per_page', 1);
            }

        // fallback in case we have no sticky posts
        // and we are not on the first page
        } else {
            $query->set('posts_per_page', $posts_per_page);
        }
    }
}


编辑

如果我们希望设置的每页帖子数小于或等于粘性帖子数,我将posts_per_page设置为1,这将导致13个或更多帖子$sticky_count + 1(在这种情况)仅在首页上显示(后续页面将有12条帖子)。也许可以,因为这种情况很少见,并且首页上的+1帖子可能意义不大。

这是因为Wordpress将在第一页和第一页(第一页)上显示所有即时贴。即使它们的计数大于posts_per_page参数,我们还是将posts_per_page设置为1的最小数量,因为0和负值将禁用posts_per_page参数,这将使Wordpress在第一行显示所有帖子页面。

评论


大!!我认为您需要将$ sticky_count +(12-$ sticky_count)更改为12- $ sticky_count。例如,如果我的粘性为1,则您的数学仍然为12,然后WP将粘性帖子添加为13。表示我们将显示24岁以上?

–helgatheviking
2012年12月19日在19:44



@helgatheviking:你是对的。我总是犯这样愚蠢的错误,对我而言,计算从来没有那么有趣。是的,这将导致24个职位。我已经更新了代码以解决此问题,并添加了页码检查。这可以正常工作,但是现在将出现一种情况,其中$ posts_per_page等于$ sticky_count,在这里我将posts_per_page参数设置为1,我认为这是可以的,因为这种情况可能很少见,并且只会在第一页($ sticky_count + 1)。

–艾哈迈德(Ahmad M)
2012-12-19 21:25

感谢您的编辑!我认为这是我们可以使用粘性帖子获得的最佳解决方案。我认为,我最终可能会通过一个简单的meta键来对帖子是否具有特色进行排序。就我的理解而言,这种行为更为正常。

–helgatheviking
2012年12月20日,0:52

如果粘性帖子属于最初想要的posts_per_page的一部分,则无法解决此问题。帖子总数将减少,但粘性帖子不会将其增加,因为它们是正常订购日期集的一部分。

–安德鲁·基伦(Andrew Killen)
18年8月1日在7:45

#2 楼

如果粘性帖子位于第一页,则会出现问题。

解决方案是减少第一页粘性帖子的粘性帖子计数。

function fix_posts_per_page_with_sticky_posts( $query ) {

    if ( $query->is_main_query() ) {

        // set the number of posts per page
        $posts_per_page = 12;

        // get sticky posts array
        $sticky_posts = get_option( 'sticky_posts' );

        // get queried post ids array
        $ids = array();
        $args = array(
            'post_type' => 'post',
            'post_per_page' => $posts_per_page,
            'paged' => 1
        );

        $posts = get_posts( $args );

        foreach ( $posts as $post ) {
            $ids[] = $post->ID;
        }

        // if we have any sticky posts and we are at the first page
        if ( is_array( $sticky_posts ) && ! $query->is_paged() ) {

            // count the number of sticky posts
            $sticky_count = count( $sticky_posts );

            foreach ( $sticky_posts as $sticky_post ) {
                if ( in_array( $sticky_post, $ids ) ) {
                    // decrement sticky posts count if the sticky post in on the page
                    $sticky_count--;
                }
            }

            // and if the number of sticky posts is less than
            // the number we want to set:
            if ( $sticky_count < $posts_per_page ) {
                $query->set( 'posts_per_page', $posts_per_page - $sticky_count );

            // if the number of sticky posts is greater than or equal
            // the number of pages we want to set:
            } else {
                $query->set( 'posts_per_page', 1 );
            }

        // fallback in case we have no sticky posts
        // and we are not on the first page
        } else {
            $query->set( 'posts_per_page', $posts_per_page );
        }
    }
}
add_action( 'pre_get_posts', 'fix_posts_per_page_with_sticky_posts'  );


我希望对您有所帮助

评论


您确定没有更简单,更快捷的解决方案吗?提示:您知道粘性帖子的数量和每页的帖子...

– kaiser
2014年11月28日下午16:53

到目前为止,我还没有发现更好的方法。我认为这更应该解决WP核心中的某些问题

–csag
2014年12月1日19:02



如果它处于核心地位,则其他方案将不起作用。

– kaiser
2014年12月1日在20:25

这是一个已知的错误,可以在core.trac.wordpress.org/ticket/27282处进行跟踪。

–将
17年9月25日在21:06

@kaiser Ahmad M的解决方案不考虑无论粘性状态如何都会显示在首页上的粘性帖子。这可能会导致首页上显示的帖子太少(WordPress v4.9.7)。这个答案更好,因为它可以解决这个问题。

–雅各布丁
18年7月17日在15:14



#3 楼

我将上述两个答案整理为一个,这样它就不会加载不必要的WP_Query,解决了第一页上是否发粘的问题,减少了使用更快速的代码处理信息的时间。

function modify_main_query( $query ) {
   if ( ( $query->is_home() || is_front_page() ) && $query->is_main_query() ) {
         // set the number of posts per page
        $posts_per_page = 12;
        // get sticky posts array
        $sticky_posts = get_option( 'sticky_posts' );
        // if we have any sticky posts and we are at the first page
        if (is_array($sticky_posts) && !$query->is_paged()) {
            // make a second query to make sure the sticky posts will still work 
            // correctly when on the first page
            // Only reply with the ID's as that is all that is needed
            $args = [
                'post_type' => 'post',
                'post_per_page' => $posts_per_page,
                'paged' => 1,
                'fields' => 'ids'
            ];
            // Array flip to reduce the time taken by 
            // using isset and not in_array
            $posts = array_flip( get_posts( $args ) );

            // count the number of sticky posts
            $sticky_count = count($sticky_posts);

            // loop the posts from the 2nd query to see if the ID's of the sticky posts
            // sit inside it.
            foreach ( $sticky_posts as $sticky_post ) {
                if(isset($posts[$sticky_post])){
                    $sticky_count--;
                }
            }
            // and if the number of sticky posts is less than
            // the number we want to set:
            if ($sticky_count < $posts_per_page) {
               $query->set('posts_per_page', $posts_per_page - $sticky_count);
            } else {
                // if the number of sticky posts is greater than or equal
                // the number of pages we want to set:
                $query->set('posts_per_page', 1);
            }
        // fallback in case we have no sticky posts
        // and we are not on the first page
        } else {
            $query->set('posts_per_page', $posts_per_page);
        }
    } 
}

add_action( "pre_get_posts", 'modify_main_query' );


#4 楼

这里写的答案可以完成工作,但是WordPress提供了一种更简单的方法。作为WP_Query类的一部分,WordPress包括current_post属性。每次调用$my_query->the_post()时,通过循环处理新帖子时,此属性将增加一。该属性最初设置为-1。
因此,为了确保始终显示正确数量的帖子(包括粘性帖子),可以按以下方式进行设置。在下面的示例中,无论有多少粘性帖子,始终都会显示两个博客帖子。
<?php
$posts_per_page = 2;
$args           = array(
    'posts_per_page' => $posts_per_page,
);

$my_query = new WP_Query( $args );

if ( $my_query->have_posts() ) :

    while ( $my_query->have_posts() && $my_query->current_post + 1 < $posts_per_page ) :

        $my_query->the_post();

        // Run code to output your posts...

    endwhile;

endif;

该方法仅在自定义查询中经过测试,但应与默认WordPress循环一起使用也是。