WordPress – how to display random posts without duplicates

To have full control over displaying posts in WordPress we can use WP_Query class and create our own query. According to documentation, if we want to to display posts in random order, we must pass suitable arguments to the query:

$args = array(
    'post_type'      => 'post',
    'orderby'        => 'rand',
);
$query = new WP_Query( $args );

But here we have two problems:

1. Pagination problem – on each page are displayed the same posts, instead of new ones, so pagination don’t work.

2. One post can be displayed several times, even on one page!



So, how to paginate posts correctly when they are displayed in random order?

When we take a look at first problem we can notice, that on each page there is displayed the same posts set. We can fix that issue when we indicate WordPress which posts should be displayed on each page. In WP_Query class we search pagination parameters and find out one that we need: ‘paged’. It show the posts that would normally show up just on page X when using the “Older Entries” link.

Now we need to know what is current page number to show WordPress what to display:

$current_page = get_query_var('paged');

$args = array(
   'post_type'      => 'post',
   'orderby'        => 'rand',
   'paged'          => $current_page,
);
$query = new WP_Query( $args );

Success! We can display random posts and retain pagination order.

Ok, first problem fixed, but what with the second one? Still our posts can be repeated several times, we don’t want that.



How to display random posts without duplicating it?

If we want to display each post only once, without repeating it, and in random order on each time, when user gets on page (but keeping posts order in the same session), we must use $_SESSION variable. To open session we must put this code in functions.php:

function prefix_start_session() {
    if( !session_id() ) {
        session_start();
    }
}
add_action( 'init', 'prefix_start_session' );

Then, in our code we can set session value:

function get_random_post() {
    if ( !isset( $_SESSION['random'] ) ) {
        $_SESSION['random'] = rand();
    }
    return $_SESSION['random'];
}

Now we can set query with arguments:

$args = array(
   'post_type'      => 'post',
   'orderby'        => 'rand(' . get_random_post() . ')',
   'paged'          => $current_page,
);
$query = new WP_Query( $args );

And display our posts in loop:

if ( query->have_posts() ) :
    while ( query->have_posts() ) : query->the_post();
        // display posts  
    endwhile;
else :
    // no content
endif;

So that’s it! Now our posts are displayed in random order without duplicates and with correctly working pagination 🙂

Joanna

Leave a Reply

Your email address will not be published. Required fields are marked *