首页 > 解决方案 > wp_query中的随机顺序与分页

问题描述

我有一个查询一些自定义帖子的简码,还添加了分页。一切正常,但我想随机化顺序。但是,当我在 args 中将 order 设置为“rand”时,我的分页中的每一页都是完全随机的——这意味着,同一个帖子可以在不同的页面上出现多次。我怎样才能随机化我所有帖子的顺序,而不是在每页级别?这是我的代码:

function slaProductsArchive( $atts ){
    global $paged;
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    $numposts = intval($atts['num']);
    $cat = $atts['cat'];
     $args = array(  
        'post_type' => 'product',
        'post_status' => 'publish',
        'posts_per_page' => $numposts, 
        'orderby' => 'rand',
        'product-category' => $cat,
        'paged' => $paged,
    );

    $loop = new WP_Query( $args ); 
    while ( $loop->have_posts() ) : $loop->the_post(); 

// Display my posts

    endwhile;
    $output .= '</div>';
    $output .= '<div class="slaPagination"><span class="prev-posts-links">' . get_previous_posts_link('<i class="fas fa-arrow-left"></i> Previous') . '</span> ';
    $output .= '<span class="next-posts-links">' . get_next_posts_link('Next <i class="fas fa-arrow-right"></i>', $loop->max_num_pages) . '</span></div>';
    
    wp_reset_postdata(); 
    return $output;
}
add_shortcode('slaProductsArchive', 'slaProductsArchive');

标签: phpwordpresscustom-post-type

解决方案


为此,我使用了 WC-Session,因为您使用的是产品,我假设您使用的是 WooCommerce。每个页面都存储在一个会话变量中,所以如果你回到上一个页面,它和以前一样。它还编写了一个单独的帖子数组,以便您可以使用post__not_in.

因此,虽然这会生成随机顺序,但一旦创建了页面,它就是刷新时的顺序。

我还更新了您的使用情况,shortcode_atts并提出了一个条件,以防没有设置产品类别。

function slaProductsArchive( $atts ){
    $atts = shortcode_atts(
        array(
            'num' => 10,
            'cat' => ''
            ),
        $atts, 'slaProductsArchive' );

    // Retrieve Previous WC Session Vars
    $done = WC()->session->get('viewed_randoms', array());
    $my_page = WC()->session->get('my_page', array());


    global $paged;
    $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
    if (!array_key_exists($paged, $my_page)) {
        if ( !empty( $atts['cat'] ) ) {
            $args = array(
                'post_type'      => 'product',
                'post_status'    => 'publish',
                'posts_per_page' => absint( $atts['num'] ),
                'orderby'        => 'rand',
                'paged'          => $paged,
                'product_cat'    => $atts['cat'],
                'post__not_in'   => $done
            );
        } else {
            $args = array(
                'post_type'      => 'product',
                'post_status'    => 'publish',
                'posts_per_page' => absint( $atts['num'] ),
                'orderby'        => 'rand',
                'paged'          => $paged,
                'post__not_in'   => $done
            );
        }
    } else {
        $args = array(
            'post_type'      => 'product',
            'post_status'    => 'publish',
            'post__in' => $my_page[$paged]
        );
    }
    // Initialize $output ** This wasn't here before ** 
    $output = '<div>';
    // A variable to store the POST ID's of this loop
    $this_loop = array();
    
    $loop = new WP_Query( $args );
    while ( $loop->have_posts() ) : $loop->the_post();
    
    // just to show something from the loop
    // You can remove this and put your own loop here 
    $output .= '<p>' . get_the_title() . ' ' . get_the_ID(). '</p>';

    // Set two array of the POST ID's
    $done[] = get_the_ID();
    $this_loop[] = get_the_ID();
    
    endwhile;
    $output .= '</div>';
    $output .= '<div class="slaPagination"><span class="prev-posts-links">' . get_previous_posts_link( '<i class="fas fa-arrow-left"></i> Previous' ) . '</span> ';
    $output .= '<span class="next-posts-links">' . get_next_posts_link( 'Next <i class="fas fa-arrow-right"></i>', $loop->max_num_pages ) . '</span></div>';

    // Set My Page Key =  Page Number - Value = each post ID
    $my_page[$paged] = $this_loop;
    // Store WC Session Var
    WC()->session->set('viewed_randoms', $done);
    WC()->session->set('my_page', $my_page);
    wp_reset_postdata();
    return $output;
}
add_shortcode( 'slaProductsArchive', 'slaProductsArchive' );

没有 WooCommerce 的替代方法

在这个方法中,我初始化了一个 PHP 会话,并使用会话 ID 的 cookie 来存储一个瞬态,因为所有其余的都是在发送标头之后完成的。因此会话仅用于会话 ID。您也可以简单地设置一个具有您想要的任何名称的 cookie,并将其用于组成的会话,纯粹用于将瞬态用作此会话。

function dd_register_session(){
    if(!session_id() && !headers_sent()) {
        session_start();
        session_write_close();
    }
}
add_action('init','dd_register_session', 1);

add_action('wp_logout', 'end_session');
add_action('wp_login', 'end_session');
add_action('end_session_action', 'end_session');

function end_session() {
    session_destroy ();
}

function slaProductsArchive( $atts ){
    $atts = shortcode_atts(
        array(
            'num' => 10,
            'cat' => ''
        ),
        $atts, 'slaProductsArchive' );

    // Retrieve Previous Session Data
    $done = $my_page = array();
    if (isset($_COOKIE['PHPSESSID'])) {
        if ( false !== ( $session_data = get_transient( $_COOKIE['PHPSESSID'] ) ) ) {
            $done = $session_data['done'];
            $my_page = $session_data['my_page'];
        }
    }
    global $paged;
    $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
    if (!array_key_exists($paged, $my_page)) {
        if ( !empty( $atts['cat'] ) ) {
            $args = array(
                'post_type'      => 'product',
                'post_status'    => 'publish',
                'posts_per_page' => absint( $atts['num'] ),
                'orderby'        => 'rand',
                'paged'          => $paged,
                'product_cat'    => $atts['cat'],
                'post__not_in'   => $done
            );
        } else {
            $args = array(
                'post_type'      => 'product',
                'post_status'    => 'publish',
                'posts_per_page' => absint( $atts['num'] ),
                'orderby'        => 'rand',
                'paged'          => $paged,
                'post__not_in'   => $done
            );
        }
    } else {
        $args = array(
            'post_type'   => 'product',
            'post_status' => 'publish',
            'post__in'    => $my_page[$paged],
            'orderby'     => 'post__in'
        );
    }
    // Initialize $output ** This wasn't here before **
    $output = '<div>';
    // A variable to store the POST ID's of this loop
    $this_loop = array();

    $loop = new WP_Query( $args );
    while ( $loop->have_posts() ) : $loop->the_post();

        // just to show something from the loop
        // You can remove this and put your own loop here
        $output .= '<p>' . get_the_title() . ' ' . get_the_ID(). '</p>';

        // Set two array of the POST ID's
        $done[] = get_the_ID();
        $this_loop[] = get_the_ID();

    endwhile;
    $output .= '</div>';
    $output .= '<div class="slaPagination"><span class="prev-posts-links">' . get_previous_posts_link( '<i class="fas fa-arrow-left"></i> Previous' ) . '</span> ';
    $output .= '<span class="next-posts-links">' . get_next_posts_link( 'Next <i class="fas fa-arrow-right"></i>', $loop->max_num_pages ) . '</span></div>';

    // Set My Page Key =  Page Number - Value = each post ID
    $my_page[$paged] = $this_loop;
    if (isset($_COOKIE['PHPSESSID'])) {
        set_transient( $_COOKIE['PHPSESSID'] , array('done' => $done, 'my_page' => $my_page), 10 * MINUTE_IN_SECONDS );
    }
    wp_reset_postdata();
    return $output;
}
add_shortcode( 'slaProductsArchive', 'slaProductsArchive' );

推荐阅读