• Hey all,

    I’ve searched this one quite a bit, and can’t quite find a resolved answer!

    Basically, I want to create a custom loop where I can set the post order to be random and the number of displayed posts to 10, for example. I then need the pagination to retain the original random post order from page to page.

    At the moment, each new page of 10 posts is randomising itself again, so you get duplicates or posts that are unlucky enough to never show!

    I did find this post, where they are able to do this, by a small addition to functions.php:

    https://wordpress.stackexchange.com/questions/31647/is-it-possible-to-paginate-posts-correctly-that-are-random-ordered

    This does seem to work for me, but the problem is, the answer given only ever offered a solution to using it on your main loop, which then overwrites all my default loops in the theme. I only want to use it on one custom loop!

    I’m just not up to the task of changing this small inclusion to the functions file so that it can just be called in a custom loop. Can anyone help?!

    Here is the code that can be added to functions.php to modify the main loop:

    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;
    }

    Thanks in advance for any help!

Viewing 15 replies - 1 through 15 (of 18 total)
  • You can set a global variable in the template, just ahead of the custom query, and check for it in the function. Then clear the variable just after the custom query.

    That way, the filter will only affect the custom query. Here is an article that shows an example:

    https://wordpress.mcdspot.com/2011/12/24/consistent-random-set-of-posts/

    That example shows the same random order of posts for all viewers each day. To show a different set for each viewer session, use the function you showed, or set the global variable using the code from that function.

    Thread Starter matstillo

    (@matstillo)

    Nice one, thanks for the reply!

    That’s joined a few dots up for me. I’ll take a look now 7 will post how I get on!

    Cheers

    Thread Starter matstillo

    (@matstillo)

    Well, I’ve now noticed a further complication!

    The list of posts I am trying to randomise is actually coming from a query string (not sure if I am using the correct terminology there!)

    Basically, I am currently calling the posts at the moment like this:

    <?php
      query_posts($query_string . '&orderby=rand');
      if (have_posts()) : while (have_posts()) : the_post();
    ?>

    This is because I needed to retain the original query because the user gets to this page by selecting a category / sub category from a drop down. So the page url looks like this:

    https://www.mydomain.com/?cat=123&submit=view

    The subsequent paged urls are like this:

    https://www.mydomain.com/page/2/?cat=123&submit=view
    https://www.mydomain.com/page/3/?cat=123&submit=view

    So what I need to do is somehow keep this original query in the new code. I have tried simply adding $query_string before the $args array, but it then breaks the random items per page again & I’m back to square 1. I’m guessing that by adding the $query_string back in, I am negating the filter in some way?

    Just leave the original query alone. The filters add to the query so the original terms should still be there. Unless, of course, there is something in the original query that would conflict with the filters, in which case it will be overridden.

    Thread Starter matstillo

    (@matstillo)

    Just in case this helps anyone else out: I got this working just with a simple combo of the arguments from the code in vtxyzzy’s link, and the code I was originally using.

    In line 22 of the code it calls the arguments outlined in that code:

    query_posts($args);

    & I just modified it to also retain the query string

    query_posts($query_string . '&' . $args);

    That way I am able to select a group of posts using a query string (a category drop down in my case), then randomise the order of the post list, with it keeping the same random order across all pages.

    Thanks for the help, vtxyzzy!

    Hey matstillo, would you mind posting your merged solution? Trying to do the same thing. Would be very helpful.

    Thanks

    atiquetedevelopers

    (@atiquetedevelopers)

    Hi, I’m trying to do the same!

    Any solutions? Thanks ??

    Szyam

    (@szyam)

    Hey guys, glad i found this post. In a situation were I’m trying to do the same.
    I’ve just started using WP a few months ago so still getting comfortable. The code I’m using to show my custom post with random four posts is:

    <?php query_posts("posts_per_page=4&orderby=rand"); ?>
    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

    Are you suggesting I can just place the code above into my functions.php and the
    $query_string . '&' . $args
    into the query_posts and get it working correctly?

    Thanks for any advice…

    Thread Starter matstillo

    (@matstillo)

    Hi all,

    Sorry I’m not being much help in this thread. Mega busy at the moment. I’ll just take a look at the Theme where I got this working & see if I can pull out the whole code.

    Thread Starter matstillo

    (@matstillo)

    <?php
    
    // Retrieve consistent random set of posts with pagination
    function mam_posts_query($query) {
       global $mam_posts_query;
       if ($mam_posts_query && strpos($query, 'ORDER BY RAND()') !== false) {
          $query = str_replace('ORDER BY RAND()',$mam_posts_query,$query);
          //print_r("<p>$query</p>");
       }
       return $query;
    }
    add_filter('query','mam_posts_query');
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    $seed = date('Ymd');  // Use date('Ymdh') to get an hourly change
    global $mam_posts_query;
    $mam_posts_query = " ORDER BY rand($seed) "; // Turn on filter
    $args = array(
       'caller_get_posts' => 1,  // Stickies will be repeated if this is not set
       'orderby' => 'rand',      // This MUST be in the query - the filter checks for it
       'paged' => $paged,
    );
    
    global $wp_query;
    query_posts(
       array_merge(
          $wp_query->query,
          $args
       )
    );
    
    $mam_posts_query = ''; // Turn off filter
    
    	if (have_posts()) : while (have_posts()) : the_post();
    ?>
    
    	<h1>Your stuff here</h1>
    
    <?php endwhile; ?>
    
    	<div>
    	   <div><?php next_posts_link('&laquo; Older Entries') ?></div>
    	   <div><?php previous_posts_link('Newer Entries &raquo;') ?></div>
    	</div>
    
    <? endif; ?>
    Thread Starter matstillo

    (@matstillo)

    Not sure what happened in this thread, as I had posted a message earlier saying that it looked like I had NOT managed to get it working after all. That post is now missing!

    The code above is as far as I got, but still doesn’t work. Each page is still being randomised.

    Hopefully someone can see what might be going on.

    Cheers!

    Has this been resolved yet?

    I think I have this working. The second function is a template tag you can use in single.php for next and previous posts link to replace the native WP version. I made it wrap from last to first post and vice versa. If you don’t want it to wrap, you’ll need to change the logic a little after this line: ‘// Find the index of the next/prev items’

    // Randomly order posts upon home page load and allow pagination
    add_filter('posts_orderby', 'edit_posts_orderby');
    
    /**
     * Randomize posts, keeping same order on subsequent Home page and single post views
     * if referer is within the site.  Home page will randomize again if reloaded.
     *
     * @param string $orderby_statement
     * @return string Modified orderby statement
     */
    function edit_posts_orderby($orderby_statement) {
    	if(!is_admin()){
    		if(is_home() && !wp_get_referer()) unset($_SESSION['seed']);
    		$seed = $_SESSION['seed'];
    		if (empty($seed)) {
    			$seed = rand();
    			$_SESSION['seed'] = $seed;
    		}
    		$orderby_statement = 'RAND('.$seed.')';
    	}
    	return $orderby_statement;
    }
    
    /**
     * Display adjacent post link with random seed.
     *
     * @param string $format
     * @param string $link
     * @param bool $previous
     */
    function get_randomized_adjacent_post_link($format='? %link', $link='%title', $previous = true, $echo = true) {
    	global $wpdb, $post;
    	$seed = $_SESSION['seed'];
    	$query = "SELECT {$wpdb->posts}.ID
    			FROM {$wpdb->posts}
    			WHERE {$wpdb->posts}.post_type = 'post'
    			AND {$wpdb->posts}.post_status = 'publish'
    			ORDER BY RAND($seed)";
    	$results = $wpdb->get_col($query);
    	$current_index = array_search($post->ID, $results);
    	// Find the index of the next/prev items
    	if($previous) {
    		$id = $results[($current_index - 1 < 0 ) ? count($results) - 1 : $current_index - 1];
    	} else {
    		$id = $results[($current_index + 1 == count($results)) ? 0 : $current_index + 1];
    	}
    	$rel = $previous ? 'prev' : 'next';
    
    	$title = get_the_title($id);
    	$string = '<a href="'.get_permalink($id).'" rel="'.$rel.'">';
    	$link = str_replace('%title', $title, $link);
    	$link = $string . $link . '</a>';
    
    	$format = str_replace('%link', $link, $format);
    
    	$adjacent = $previous ? 'previous' : 'next';
    	$the_link = apply_filters( "{$adjacent}_post_link", $format, $link );
    	if($echo) echo $the_link;
    	else return $the_link;
    }

    Hello,

    i saw a very similar function here : https://wordpress.stackexchange.com/questions/31647/is-it-possible-to-paginate-posts-correctly-that-are-random-ordered

    This works indeed, when adding this function to functions.php BUT it replaces every other custom order function (replaces the ordering of the main loop).

    I have a page template in which i allow custom ordering of posts, sth `like if ($_GET[‘order’] == “random”) {
    // do wp_query using orderby = rand
    } else {
    // do wp_query using orderby = date
    }`

    How would I apply your function in this case?

    You could probably modify this function as such:

    /**
     * Randomize posts, keeping same order on subsequent Home page and single post views
     * if referer is within the site.  Home page will randomize again if reloaded.
     *
     * @global $_GET['order'] default or 'random' sets random, 'date' sets date.
     *
     * @param string $orderby_statement
     * @return string Modified orderby statement
     */
    function edit_posts_orderby($orderby_statement) {
    	if(!is_admin()){
    		switch ($_GET['order']) {
    			case "date":
    				break;
    			case "random":
    			default:
    				if(is_home() && !wp_get_referer()) unset($_SESSION['seed']);
    				$seed = $_SESSION['seed'];
    				if (empty($seed)) {
    					$seed = rand();
    							$_SESSION['seed'] = $seed;
    				}
    				$orderby_statement = 'RAND('.$seed.')';
    		}
    
    	}
    	return $orderby_statement;
    }
Viewing 15 replies - 1 through 15 (of 18 total)
  • The topic ‘Random Post order not working with pagination’ is closed to new replies.