Repeating posts when paginating random posts

In all honesty, I really think that all your misery is caused by your pagination function as we have briefly discussed a while ago.

You do have a couple of issues here that are contributing factor to the problems you are experiencing

  • Changing the main query for a custom query for what ever reason is almost always a big headache and should be avoided at all times. The main query can be very easily modified by pre_get_posts to suite your needs. I have done a post a while ago about this complete issue that you can go and read up on

  • Nullifying the main query is exactly the same as using query_posts, which you should never use. This might be one of the big reasons why your pagination outright fails

Note: This function isn’t meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).

I think the easiest way to debug this and moving forward is to get rid of your custom query. Copy this code and paste this in your taxonomy.php file.

<div class="container">

<?php 
while( have_posts() ) { 
    the_post(); 
?>

    <!--product image and title-->
    <div>
      <a href="https://wordpress.stackexchange.com/questions/172206/<?php the_permalink(); ?>"><img src="<?php the_field('image'); ?>" alt="Name of Product"></a>
    </div><!--product-image-->

    <div>
    <?php the_field('title'); ?>
    </div><!--title end-->

<?php } ?>


<?php 

//getting paginations in numbers
global $wp_query;

$total_pages = $wp_query->max_num_pages;

  $current_page = max(1, get_query_var('paged'));

  echo paginate_links(array(
      'base' => get_pagenum_link(1) . '%_%',
      'format' => '/page/%#%',
      'current' => $current_page,
      'total' => $total_pages,
      'before_page_number' => '<div class="pagination-navigation">',
      'after_page_number' => '</div>'

    ));
?>

</div><!--container end-->

You should now at least get the correct posts, in order of post date. First make sure that this is working correctly. Don’t worry if the pagination doesn’t work, as I said, I get an idea something is wrong with your function

You can now use pre_get_posts to change the order of your posts and add custom posts_per_page

Paste the following in your functions.php

add_action( 'pre_get_posts', function ( $q ) {
    if( !is_admin() && $q->is_main_query() && $q->is_tax() ) {
        $q->set( 'posts_per_page', 10 );
        $q->set( 'orderby', 'rand' );
    }
});

Post type should be included by default on the taxonomy page so it would not be necessary to add this into your pre_get_posts action

This should give you the correct output from your template. As I said, make sure that this is working, if the pagination is not working, don’t worry about that now, first get your output as it should.

If all is working fine, except pagination, you will need to look at your pagination function. Let me know if your pagination does not work after you have made all these changes

EDIT 1

I’ve searched a bit for possible solutions to this problem and came up with this article written by Hugh Lashbrooke

PROBLEM

As soon as you navigate to the second page of the results, the posts are returned randomly once again and you get an entirely different set of posts that may or may not contain posts that you have already viewed

SOLUTION

…we will use MySQL’s RAND() function and supply it with a seed value so it uses the same random order on every subsequent page load. To do this we will store a random string as a PHP session variable so it can be used by MySQL as a reference for the order to use for each page.

NOTE ABOUT THE CODE

You will notice one extra operation on line 7 of this snippet – we also reset the seed value every time the first page of the posts are loaded. This means that as long as someone stays on the paginated pages they will see a consistent set of results, but once they go back to the first page the randomisation will reset and they will see the posts in a completely different order.

session_start();

add_filter( 'posts_orderby', 'randomise_with_pagination' );
function randomise_with_pagination( $orderby ) {

    if( is_tax() ) {

        // Reset seed on load of initial archive page
        if( ! get_query_var( 'paged' ) || get_query_var( 'paged' ) == 0 || get_query_var( 'paged' ) == 1 ) {
            if( isset( $_SESSION['seed'] ) ) {
                unset( $_SESSION['seed'] );
            }
        }

        // Get seed from session variable if it exists
        $seed = false;
        if( isset( $_SESSION['seed'] ) ) {
            $seed = $_SESSION['seed'];
        }

            // Set new seed if none exists
            if ( ! $seed ) {
                $seed = rand();
                $_SESSION['seed'] = $seed;
            }

            // Update ORDER BY clause to use seed
            $orderby = 'RAND(' . $seed . ')';
    }

    return $orderby;
}

EDIT 2

This code is working perfectly, I have now tested it over and over again. If this does not work for you, you have to recheck your code. You have to take note of the following.

  • The code given only targets the taxonomy archive pages, that is why the is_tax() conditional tag is used. If you need this on any other template, you will need to modify/change that conditional tag

  • The posts don’t duplicate, and the posts are only reset when the first post is visited, no other pages are affected. Make sure that your results are not being cached.

As a final attempt, here is the only code that you should have from this answer in your functions.php

add_action( 'pre_get_posts', function ( $q ) {
    if( !is_admin() && $q->is_main_query() && $q->is_tax() ) {
        $q->set( 'posts_per_page', 10 );
        $q->set( 'orderby', 'rand' );
    }
});
session_start();

add_filter( 'posts_orderby', 'randomise_with_pagination' );
function randomise_with_pagination( $orderby ) {

    if( is_tax() ) {

        // Reset seed on load of initial archive page
        if( ! get_query_var( 'paged' ) || get_query_var( 'paged' ) == 0 || get_query_var( 'paged' ) == 1 ) {
            if( isset( $_SESSION['seed'] ) ) {
                unset( $_SESSION['seed'] );
            }
        }

        // Get seed from session variable if it exists
        $seed = false;
        if( isset( $_SESSION['seed'] ) ) {
            $seed = $_SESSION['seed'];
        }

            // Set new seed if none exists
            if ( ! $seed ) {
                $seed = rand();
                $_SESSION['seed'] = $seed;
            }

            // Update ORDER BY clause to use seed
            $orderby = 'RAND(' . $seed . ')';
    }

    return $orderby;
}