29

I found this problem on Wordpress Support and the topic unfortunately is now closed. I have this same issue... (read below)


We have created a site where members can recommend things like favourite books, movie, songs, etc. For this problem I will use the Movies page as an example.

The "Movies" page is ultimately a custom page template that asks wordpress to display a random list of ALL posts that have been given the category "movies" (category 31). It displays the title of these movies in random order using the code below.

<?php 
$rand = new WP_Query("cat=31&showposts=-1&orderby=rand"); 
while($rand->have_posts()) : $rand->the_post();
?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?>
<?php endwhile; ?>

Problem is the list is getting rather long and I would like to split it up into two or more pages of about 10 movies each. To achieve this, I have used the code below.

<?php 
$page = (get_query_var('paged')) ? get_query_var('paged') : 1; 
query_posts("cat=31&orderby=rand&showposts=10&paged=$page"); 
while ( have_posts() ) : the_post() 
?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?>
<?php endwhile; ?>

But there is a problem because although it splits up the data into pages of 10 posts each (paginates), it fails to include a new set of 10 posts on page 2 and so forth. In other words, because it is listing things in a random order, it just goes out and gets another 10 random posts (or in this case movie titles). As a result, we have some repeated movie title posts instead of a new set of 10 random movie titles on page 2, etc.

My question is - what can I add to this code to get wordpress to "remember" which random 10 posts it included on page 1, and then have it get a new set of 10 posts to put on pages 2, 3, etc. until all posts are displayed. I would like there to be only one occurrence of a post per page when sorted randomly in sets of 10.

38

You can use a filter to modify the ORDER BY statement of WP_query.

That way you can manually set the query to use ORDER BY RAND($seed);

Mysql RAND() accepts a seed as an optional argument. Using a seed, it will return the same randomized result set each time.

So you can generate a random number on the first page load then store it in a SESSION variable and use that as the $seed for further paginated requests.

If you are trying to acheive this on your main loop for instance, you could add the following to your functions.php file.

session_start();

add_filter('posts_orderby', 'edit_posts_orderby');

function edit_posts_orderby($orderby_statement) {

    $seed = $_SESSION['seed'];
    if (empty($seed)) {
      $seed = rand();
      $_SESSION['seed'] = $seed;
    }

    $orderby_statement = 'RAND('.$seed.')';
    return $orderby_statement;
}
  • perfect solution. thank you so much – Faisal Ramzan Nov 11 at 13:39
3

Since the last versions of WordPress, you can now add a seed to the value of the orderby parameter of WP_Query:

$query = new WP_Query([
    'orderby' => 'RAND($seed)',
    ...
]);

$seed is a random number. You should store it as a PHP session variable. Do not forgot to enable PHP session in WordPress by calling session_start() in you functions.php:

if (!session_id()) {
    session_start();
}

With this syntax you don't need to use the posts_orderby filter. Moreover, you don't have to make sure that the filter is only applied to the targeted WP_Query.

For further information please read this ticket on WordPress Core.

  • the answer might be technically correct, but it sucks. please edit and explain the why of it instead of sending people to RTFM – Mark Kaplun Jul 21 '17 at 13:54
  • I have edited my answer to explain why it could be a better choice instead of using a filter in this particular case. – Guicara Jul 21 '17 at 14:16
  • a late +1, but cookies should be used instead of sessions. basically sessions should never be used as they are too problematic in all kinds of ways. – Mark Kaplun Feb 2 '18 at 7:16
  • helped a lot .. thanks – Faisal Ramzan Nov 11 at 13:39

protected by fuxia Sep 4 '13 at 7:48

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.