Random Posts Shortcode
Adds a [random_posts] shortcode that lists a few random posts, optionally from chosen categories or another post type, without running a slow random database query on every page view.
Opens WPIDE on
Code
// How long the list of posts to pick from is cached, in minutes.
$wpide_random_posts_cache_minutes = 60;
// How many of the newest posts the random picks come from.
$wpide_random_posts_pool_size = 200;
add_shortcode( 'random_posts', function ( $atts ) use ( $wpide_random_posts_cache_minutes, $wpide_random_posts_pool_size ) {
$atts = shortcode_atts( array(
'count' => 5,
'post_type' => 'post',
'category' => '',
), $atts, 'random_posts' );
$count = max( 1, min( 50, absint( $atts['count'] ) ) );
$post_type = sanitize_key( $atts['post_type'] );
if ( ! post_type_exists( $post_type ) || ! is_post_type_viewable( $post_type ) ) {
return '';
}
$query = array(
'post_type' => $post_type,
'post_status' => 'publish',
'posts_per_page' => max( $count, (int) $wpide_random_posts_pool_size ),
'fields' => 'ids',
'has_password' => false,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'orderby' => 'date',
'order' => 'DESC',
);
// category="news" or category="news,12" (slugs or IDs).
$categories = array_filter( array_map( 'trim', explode( ',', (string) $atts['category'] ) ) );
if ( $categories && is_object_in_taxonomy( $post_type, 'category' ) ) {
$ids = array_map( 'intval', array_filter( $categories, 'ctype_digit' ) );
$slugs = array_map( 'sanitize_title', array_diff( $categories, array_filter( $categories, 'ctype_digit' ) ) );
$query['tax_query'] = array( 'relation' => 'OR' );
if ( $ids ) {
$query['tax_query'][] = array( 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => $ids );
}
if ( $slugs ) {
$query['tax_query'][] = array( 'taxonomy' => 'category', 'field' => 'slug', 'terms' => array_values( $slugs ) );
}
}
// The candidate list is cached, so pages do not run a slow ORDER BY RAND() query.
$cache_key = 'wpide_random_posts_' . md5( (string) wp_json_encode( $query ) );
$pool = get_transient( $cache_key );
if ( ! is_array( $pool ) ) {
$pool = array_map( 'intval', get_posts( $query ) );
set_transient( $cache_key, $pool, max( 1, (int) $wpide_random_posts_cache_minutes ) * MINUTE_IN_SECONDS );
}
if ( is_singular() ) {
$pool = array_diff( $pool, array( get_queried_object_id() ) );
}
if ( ! $pool ) {
return '';
}
shuffle( $pool );
$posts = get_posts( array(
'post__in' => array_slice( $pool, 0, $count ),
'post_type' => $post_type,
'posts_per_page' => $count,
'orderby' => 'post__in',
) );
$items = '';
foreach ( $posts as $post ) {
$items .= '<li><a href="' . esc_url( get_permalink( $post ) ) . '">' . esc_html( get_the_title( $post ) ) . '</a></li>';
}
return '' === $items ? '' : '<ul class="wpide-random-posts">' . $items . '</ul>';
} );
Notes
Examples: [random_posts], [random_posts count="3" category="news,reviews"], [random_posts post_type="page" count="4"]. Categories can be slugs or IDs. The list of candidate posts is cached (60 minutes by default) and a new random pick is made from it on every uncached page view. The post being viewed is never included.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.