一个页面上有2个循环-第二个循环的分页忽略已排除帖子的数组

时间:2016-03-06 作者:Maciek Wrona

我在一页上有两个循环。第一个按随机顺序显示11篇最近的帖子,并将每个帖子ID推入do_not_duplicate大堆

$argsRandom = array(
  \'numberposts\' => 11,
  \'fields\'      => \'ids\'
);

$latest_posts =  get_posts( $argsRandom );
shuffle( $latest_posts );

$counter = 0;
$args = array(
    \'posts_per_page\' => 11, 
    \'post__in\' => $latest_posts , 
    \'orderby\' => \'post__in\', 
    \'order\' => \'ASC\'
);
$loop = new WP_Query($args);

$do_not_duplicate[] = $post->ID;

while ($loop-> have_posts()) : $loop->the_post();
    $do_not_duplicate[] = $post->ID;
第二个应该显示所有忽略了do_not_duplicate. 它在第一页上运行良好,但在上发生了一些奇怪的事情/page/3/ 显示了最后3篇帖子,所有帖子都来自do_not_duplicate 大堆我不明白为什么会这样。

$paged = ( get_query_var( \'paged\' ) ) ? get_query_var( \'paged\' ) : 1;
$args2 = array(
    \'posts_per_page\' =>11,
    \'post__not_in\' => $do_not_duplicate,
    \'orderby\' => \'date\',
    \'order\' => \'ASC\',
    \'paged\' => $paged
    );


$loop2 = new WP_Query($args2);
while ($loop2-> have_posts()) : $loop2->the_post();
我正在处理索引页,只在上运行第一个循环!is_paged()

1 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

因为这应该是主页上的主循环,所以有一种更好的方法可以实现这一点,而无需运行任何自定义查询。永远不要用自定义查询替换主查询。我不打算详述,因为我已经做了quite extensive answer 这是你必须去读的。

我们可以使用主查询并根据自己的意愿对其进行修改,以便通过可用的过滤器和操作来调整它以满足我们的需要

总体规划-乐高部分你需要在第一页上发表22篇文章,从那里开始只需要11篇。棘手的部分是

第1页,我们需要随机排列前11篇文章,然后按正常顺序排列下11篇文章。

重新计算分页,因为在大多数情况下,最后一页404\'ing取决于帖子数量

我们需要做的是:

最重要的是,删除自定义查询并返回上的主循环index.php. 你的index.php 应如下所示:(根据您的具体需要进行调整,这是最低要求)

if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();

        // Your markup and template tags to display posts

    } 
    // Your paging function
} else {
    // Your message to display when there is no posts
} 
将每页的帖子数设置为11。我们可以手动或在后端使用该设置

通过pre_get_posts 我们将在第11页增加11篇帖子。在这个阶段,你应该在第一页上有22篇文章,按日期排序。其他页面应该有11篇帖子,最有可能是最后一页404\'ing。

要整理分页,我们需要通过found_posts 滤器这个$max_num_pages 负责计算分页的查询对象中的属性使用每页的帖子数量和找到的帖子数量来计算将有多少页。排序完成后,除了第一页上的前11篇帖子外,所有内容都将正常运行

要将第一页的前11篇文章随机排列,我们将通过the_posts 滤器此过滤器在实际运行循环以显示帖子之前执行。完成后,你应该得到你想要的结果

代码-使用我们的乐高积木

Few notes

所有代码都经过测试,但可能仍然有问题。如果您有任何问题,请告诉我

该代码至少需要PHP 5.4

根据需要进行调整。所有代码都将进入自定义插件(推荐)或主题的函数文件

第一部分-帮手因为我们有重复的代码,让我们创建可过滤的帮手

/**
 * Return the amount of posts per page, which by default is 11
 */
function wpse_219896_ppp ()
{
    return apply_filters( \'wpse_219896_ppp\', 11 );
}

/**
 * Returns the offset to use, which by default is 11
 */
function wpse_219896_offset ()
{
    return apply_filters( \'wpse_219896_offset\', 11 );
}
我们可以通过以下示例简单地调整这些函数的任何输出:

add_filter( \'wpse_219895_ppp\', function ( $ppp )
{
    return 10;
}
这样做只是为了保持代码的可维护性

第二部分-pre_get_posts

我们现在将通过pre_get_posts 行动

add_action( \'pre_get_posts\', function ( $q )
{
    if (    $q->is_home()       // Only target the home page
         && $q->is_main_query() // Only target the main query
    ) {
        // First set our variables
        $ppp          = wpse_219896_ppp();
        $offset       = wpse_21896_offset();
        $current_page = get_query_var( \'paged\', 1 );

        // Target the first page first
        if ( !$q->is_paged() ) {
            // Add our offset to $ppp
            $q->set( \'posts_per_page\', ( $ppp + $offset ) );
        } else { 
            /**
             * Lets target all the paged pages now.
             *
             * Because we are breaking the internal calculation for post offset and pagination,
             * we must manually recalculate and set it
             */
            $paged_offset = $offset + ( ( $current_page -1 ) * $ppp );

            $q->set( \'posts_per_page\', $ppp          );
            $q->set( \'offset\',         $paged_offset );
        }
    }
});
我们现在已经处理了每页的帖子,第一页将有22篇帖子,其余将有11篇

第三部分-found_posts 过滤器现在需要调整分页才能正常工作

add_filter( \'found_posts\', function ( $found_posts, $q )
{
    if (    $q->is_home()       // Only target the home page
         && $q->is_main_query() // Only target the main query
    ) {    
        $offset = wpse_219896_offset();

        // Make sure we have atleat more posts found than the offset
        if ( $offset >= $found_posts ) 
            return $found_posts;

        $found_posts = $found_posts - $offset;
    }
    return $found_posts;
}, 10, 2 );
第四部分-the_posts 筛选我们现在需要做的就是对第一页的前11篇文章进行随机排序

add_filter( \'the_posts\', function ( $posts, $q )
{
    if (     $q->is_home()       // Only target the home page
         &&  $q->is_main_query() // Only target the main query
         && !$q->is_paged()      // Only target page one
    ) {        
        $offset = wpse_219896_offset();

        // Make sure that have more than 11 posts, if not, randomly sort all
        if ( $offset >= $q->post_count ) {
            shuffle( $posts );
            return $posts;
        }

        /**
         * We have more posts than our offset, lets split the array and 
         * randomize the first set of posts
         */
        $array_1 = array_slice( $posts, 0, $offset );
        $array_2 = array_slice( $posts, $offset, \'\', true );

        // Randomize array_1
        shuffle( $array_1 );

        // Merge the two slices into one array again
        $posts = array_merge( $array_1, $array_2 );
    }
    return $posts;
}, 10, 2 );
这应该能解决一切问题。

现在,我们可以将其简化为一个插件。下面是最终代码的样子

<?php
/*
Plugin Name: Random posts per page
Plugin URI:  https://wordpress.stackexchange.com/q/219896/31545
Description: Different amount of posts  per page with x amount shown randomly
Version:     1.0.0
Author:      Pieter Goosen
Author URI:  https://wordpress.stackexchange.com/users/31545/pieter-goosen
License:     GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/

/**
 * Return the amount of posts per page, which by default is 11
 */
function wpse_219896_ppp ()
{
    // Filter the amount of posts per page
    return apply_filters( \'wpse_219896_ppp\', 11 );
}

/**
 * Returns the offset to use, which by default is 11
 */
function wpse_219896_offset ()
{
    // Filter the offset of posts
    return apply_filters( \'wpse_219896_offset\', 11 );
}

add_action( \'pre_get_posts\', function ( $q )
{
    if (    $q->is_home()       // Only target the home page
         && $q->is_main_query() // Only target the main query
    ) {
        // First set our variables
        $ppp          = wpse_219896_ppp();
        $offset       = wpse_219896_offset();
        $current_page = get_query_var( \'paged\', 1 );

        // Target the first page first
        if ( !$q->is_paged() ) {

            // Add our offset to $ppp
            $q->set( \'posts_per_page\', ( $ppp + $offset ) );

            // Filter the_posts to randomize first x amount of posts
            add_filter( \'the_posts\', function ( $posts, $q ) use ( $ppp, $offset )
            {
                remove_filter( current_filter(), __FUNCTION__ );

                if ( !$q->is_main_query() ) 
                    return $posts;

                // Make sure that have more than $offset posts, if not, randomly sort all
                if ( $offset >= count( $q->posts ) ) {
                    shuffle( $posts );
                    return $posts;
                }

                /**
                 * We have more posts than our offset, lets split the array and 
                 * randomize the first set of posts
                 */
                $array_1 = array_slice( $posts, 0, $offset );
                $array_2 = array_slice( $posts, $offset, $ppp, true );

                // Randomize array_1
                shuffle( $array_1 );

                // Merge the two slices into one array again
                $posts = array_merge( $array_1, $array_2 );

                return $posts;
            }, 10, 2 );

        } else { 
            /**
             * Lets target all the paged pages now.
             *
             * Because we are breaking the internal calculation for post offset and pagination,
             * we must manually recalculate and set it
             */
            $paged_offset = $offset + ( ( $current_page -1 ) * $ppp );

            $q->set( \'posts_per_page\', $ppp          );
            $q->set( \'offset\',         $paged_offset );
        }

        // Filter the found_posts property of the query
        add_filter( \'found_posts\', function ( $found_posts, $q ) use ( $offset )
        {
            remove_filter( current_filter(), __FUNCTION__ );

            if ( !$q->is_main_query() )
                return $found_posts;

            // Make sure we have at leat more posts found than the offset
            if ( $offset >= $found_posts ) 
                return $found_posts;

            return $found_posts - $offset;
        }, 10, 2 );
    }
});

相关推荐

Duplicated <a> tag in loop

我坚持这个问题,看起来很简单,但找不到解决它的方法。我有这样的循环:<div class="features-items__wrapper"> <h2><?php echo $currentTitle; ?></h2> <?php global $post; $post_sl