You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让两个WP_Query用相同随机排序避免AJAX加载重复文章?

解决WordPress随机排序AJAX加载更多不重复且全量展示的问题

我最近碰到了一个挺常见的WordPress开发需求:首页要展示9篇随机排序的自定义文章类型my_posts,点击“加载更多”按钮通过AJAX每次再加9篇,核心要求是不能重复加载文章,且能展示全部32篇文章。

一开始我尝试了常规思路:把已显示的文章ID存入数组,用post__not_in参数排除,但遇到了棘手的问题——每次从剩余文章里随机取9篇,最后总会有部分文章无法被加载到(总共只显示了约28篇,而非全部32篇)。

后来我换了思路,通过预先生成全局随机ID序列,再分页截取加载的方式解决了问题,完整方案如下:


核心思路

先一次性获取所有随机排序的文章ID,把这个随机序列作为全局基准,后续每次加载都从这个序列里按页码截取9个ID来查询文章。这样既保证了随机顺序,又不会重复,还能确保所有文章都能被加载到。

1. 首次查询并渲染前9篇文章

先获取所有my_posts类型的文章并随机排序,只渲染前9篇,同时把剩余的文章ID存起来:

<?php
// 一次性获取所有随机排序的文章
$args = array( 
    'post_type' => 'my_posts', 
    'posts_per_page' => -1, 
    'orderby' => 'rand' 
);
$the_query = new WP_Query($args);

$index = 0; 
$idsInt = array(); 

while ($the_query->have_posts()): $the_query->the_post(); 
    if ($index < 9) : 
        // 渲染前9篇文章
        get_template_part('part-template/content', get_post_format()); 
        $index++; 
    else : 
        // 存储剩余文章的ID
        array_push($idsInt, get_the_ID()); 
    endif; 
endwhile;
wp_reset_postdata();
?>

2. 转换ID数组为可传递的字符串格式

把存储的剩余ID数组转成适合在HTML属性中传递的字符串格式:

<?php
$index = 0; 
$idsString = ''; 
foreach ($idsInt as $id) { 
    if ($index == 0) { 
        $idsString .= " \"" . $id . "\""; 
    } else { 
        $idsString .= ", \"" . $id . "\""; 
    } 
    $index++; 
}
?>

3. 渲染加载更多按钮并传递参数

在页面底部添加加载更多按钮,通过data-*属性传递剩余ID列表、AJAX地址和当前页码:

<div class="text-center">
    <a id="btn-load-more" 
       data-id='[<?php echo $idsString ?>]' 
       class="home-load-more" 
       data-page="1" 
       data-url="<?php echo admin_url('admin-ajax.php'); ?>"
    >
        <span class="text"><?php _e('Load More') ?></span>
    </a>
</div>

4. 编写AJAX请求脚本(script.js)

实现点击按钮时的AJAX逻辑,把页码和ID列表传递给后台处理函数:

$(document).on('click', '.home-load-more', function () { 
    let that = $(this); 
    let page = that.data('page'); 
    let newPage = page + 1; 
    let ajaxurl = that.data('url'); 
    let ids = that.data('id'); 

    $.ajax({ 
        url: ajaxurl, 
        type: 'post', 
        data: { 
            page: page, 
            action: 'home_load_more', 
            foo : ids 
        }, 
        error: function (response) { 
            console.log(response); 
        }, 
        success: function (response) { 
            if (!(response === "")) { 
                that.data('page', newPage); 
                $('.my_row').append(response); 
            } 
        } 
    }); 
});

5. 编写后台AJAX处理函数

在主题的functions.php中添加处理AJAX请求的函数,根据页码截取对应9个ID,然后查询并渲染文章:

function home_load_more() { 
    $ids = $_POST['foo']; 
    $paged = $_POST["page"]; 
    $postIn = array(); 

    // 根据当前页码计算要截取的ID位置
    for ($i = 0; $i < 9; $i++) { 
        $currentIdIndex = ($paged - 1) * 9 + $i;
        // 没有更多ID时终止循环
        if (!isset($ids[$currentIdIndex])) { 
            break; 
        } 
        array_push($postIn, $ids[$currentIdIndex]); 
    } 

    if (empty($postIn)) { 
        wp_reset_postdata();
        die();
    }

    // 根据截取的ID查询文章,保持预先生成的随机顺序
    $query = new WP_Query(array( 
        'post_type' => 'my_posts', 
        'orderby' => 'post__in', 
        'post__in' => $postIn 
    )); 

    if ($query->have_posts()) { 
        while ($query->have_posts()) { 
            $query->the_post(); 
            get_template_part('part-template/content', get_post_format()); 
        } 
    } 
    wp_reset_postdata(); 
    die(); 
}
// 注册AJAX动作,支持登录和未登录用户
add_action('wp_ajax_home_load_more', 'home_load_more');
add_action('wp_ajax_nopriv_home_load_more', 'home_load_more');

这个方案完美解决了重复加载和无法全量展示的问题,如果你有更优的实现思路,欢迎在评论区交流~

内容的提问来源于stack exchange,提问作者Mathias Nicod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:13:10