Randomization With WP Engine Cache

Be default, WP Engine disables WordPress queries with a random order. You can enable it, but that will disable their caching system, so it’s not a good idea. Here is a run through on how to properly use randomization with a WP Engine caching system with some explanations of what’s happening.

PHP random functions still work with some caching delays

The follow code is looping through an ACF Gallery and displaying 10 random images using a PHP function called shuffle. Without caching, PHP would randomize the image selection on each request. With WP Engine caching, this PHP will randomize every 10 minutes which is the length of time a page is held in cache. In most situations I’ve encountered. this delayed randomization works just fine .

<?php 
 $images = get_field('photo_strip');

 // Randomizes array
 shuffle($images); 

 // Limit to 10 images
 $images = array_slice($images, 0, 10);

 if( $images ): ?>
 <ul class="photostrip">
   <?php foreach( $images as $image ): ?>
     <li>
        <img src="<?php echo $image['sizes']['medium']; ?>" alt="<?php echo $image['alt']; ?>" />
     </li>
   <?php endforeach; ?>
 </ul>
 <?php endif; ?>

Using WordPress transient to proper handle random queries

The first step to using random queries with WP Engine is enabling their  Allow ORDER BY RAND() selection. This is done by going to /wp-admin/admin.php?page=wpengine-common as shown here.

Screen Shot 2017-03-22 at 9.31.23 AM.png

With that you can now use a WP Query with a random order. Here’s an example of a random slider.

<?php
// WP_Query arguments
$args = array(
   'post_type' => array( 'slider' ),
   'orderby' => 'rand',
);

// The Query
$query = new WP_Query( $args );

In this case, logged in users will see the randomization on each request, however users that are not logged in will see this randomize every 10 minutes due to WP Engine’s caching. Hitting the database on each request is generally not a good idea. To improve performance you can add database caching using a WordPress Transient. The following code will store the random query in a transient which is set to expire every 10 minutes. This means even if 1000 logged in users request the random slider page, the database will only run once and be cached, which will significantly improve performance.

<?php
// WP_Query arguments
$args = array(
   'post_type' => array( 'slider' ),
   'orderby' => 'rand',
);

// The Query, pull from transient if exists
if ( false === ( $query = get_transient( 'random_slider_query_results' ) ) ) {
   // It wasn't there, so regenerate the data and save the transient
   $query = new WP_Query( $args );
   set_transient( 'random_slider_query_results', $query, 10 * MINUTE_IN_SECONDS );
}

Putting this all together, here is sample of what a random slider using ACF would look like.

<?php
// WP_Query arguments
$args = array(
   'post_type' => array( 'slider' ),
   'orderby' => 'rand',
);

// The Query, pull from transient if exists
if ( false === ( $query = get_transient( 'random_slider_query_results' ) ) ) {
   // It wasn't there, so regenerate the data and save the transient
   $query = new WP_Query( $args );
   set_transient( 'random_slider_query_results', $query, 10 * MINUTE_IN_SECONDS );
}

// The Loop
if ( $query->have_posts() ) {
   while ( $query->have_posts() ) {
      $query->the_post(); 
      $image_id = get_field('image');
      $image = wp_get_attachment_image_src( $image_id, "slider" );
      $link = get_field('link');  ?>
      <li>
         <?php if($link) { ?><a href="<?php echo $link; ?>"><?php }?>
         <img src="<?php echo $image[0]; ?>">
         <?php if($link) { ?></a> <?php }?>
      </li>
<?php 
   }
} else {
   // no posts found
}

// Restore original Post Data
wp_reset_postdata();