Search code examples
phpwordpressrandompaginationsticky

Consistent random set of posts with stickies


Using WordPress, on my main page I'd like to be able to make a query of random posts that are consistent throughout a pagination, while stickies are still shown first. I've gotten as far as to create a consistent flow but I'm missing out on the stickies which show up randomly like the rest of the posts.

function custom_query($query) {
    global $custom_query;
    if ( $custom_query && strpos($query, 'ORDER BY RAND()') !== false ) {
        $query = str_replace( 'ORDER BY RAND()', $custom_query, $query );
    }
    return $query;
}

add_filter( 'query', 'custom_query' );
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$seed = $_SESSION['seed'];

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

global $custom_query;
$custom_query = " ORDER BY rand($seed) ";

$args = array(
    'caller_get_posts' => 1,
    'orderby' => 'rand',
    'paged' => $paged,
);

query_posts($args);
$custom_query = '';

Edit: Based on your suggestions I managed to solve it using the code below:

$sticky_post_ids = get_option('sticky_posts');
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 );
   }
   return $query;
}
add_filter( 'query','mam_posts_query' );
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$seed = date('Ymdh'); // Sets an hourly random cache
global $mam_posts_query;
$mam_posts_query = " ORDER BY rand($seed) ";

$args = array(
    'orderby' => 'rand',
    'paged' => $paged,
    'post__not_in' => get_option( 'sticky_posts' )
);
$projects = query_posts($args);
$mam_posts_query = '';

if ( $paged === 1 ) {
    $stickies = get_posts( array('include' => $sticky_post_ids) );
    $projects = array_merge( $stickies, $projects );
}

Thanks for the advice!


Solution

  • I know that the description in the codex wp_query page is a bit confusing , but I believe that all you need to do is set

    'ignore_sticky_posts' => 0.

    That in my experiments worked, but of course while dealing with queries , I do not know where or when in another location might your query have changes ..

    At any rate , if that does not work for you , you can also get the stickies with

    $sticky = get_option( 'sticky_posts' );

    and then set the query like this :

    'post__in' => get_option('sticky_posts')

    or even so : (note the not_in)

     $query->set( 'post__not_in', get_option( 'sticky_posts' ) );
    

    Do note that by default the stickies are shown only on the home page .

    you might also use a double loop approach :

    $stickyQuery = new WP_Query( array(
            'cat'                    => $your_category,// example   
            'ignore_sticky_posts'    => 0,
            'post__in'               => get_option( 'sticky_posts' ),
            'posts_per_page'         => -1             //Get ALL and ONLY the stickies, or how many you want
        );
    while( $stickyQuery->have_posts() ) : $stickyQuery->the_post();
    
       //... ( Sticky Posts should show )
    
    endwhile;
    wp_reset_query();
    
    //... ( Continue main query or start a new one excluding the last.... )