即时贴超过每页限制


21

我正在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个帖子,如果只有一个粘性帖子,您将获得12个帖子。

Answers:


12

这是一种通过获取粘性帖子数(如果有)并将其包含在计算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为一个,这样$sticky_count + 1只会在第一个帖子上产生13个或更多的帖子(在这种情况下)页面(后续页面将有12个帖子)。也许可以,因为这种情况很少见,并且首页上的+1帖子可能意义不大。

这是因为,即使它们的计数大于posts_per_page参数,Wordpress也会在第一页和第一页(第一页)上显示所有即时贴,因此posts_per_page在这种情况下,我们将设置为,即1,因为0和负值将禁用的posts_per_page参数,这将让WordPress的,以显示第一页上的所有帖子。


大!!我认为您需要更改$sticky_count + (12 - $sticky_count)12- $sticky_count。例如,如果我的粘性为1,则您的数学仍然为12,然后WP将粘性帖子添加为13 if ($sticky_count > $posts_per_page)
helgatheviking 2012年

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

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

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

3

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

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

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

希望对您有所帮助


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

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

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

这是一个已知的错误,请在core.trac.wordpress.org/ticket/27282
Will中

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

0

我将以上两个答案都整理成了一个,这样它就不会加载不必要的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' );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.