Display Random Posts from Specific Tags or Categories

Posted on July 13, 2009 in WordPress by

When developing the colorful Quintessential Theme (opens in new tab), I initially planned on displaying five random posts from each of my most popular tags and categories in the super-slick sliding-panel sidebar. Because I am running an older version of WordPress, however, this task proved to be quite the educational experience.

In newer versions (from 2.5 I think) of WordPress, the query_posts() function enables users to display posts in random order using the orderby=rand parameter. This would have made my life easy, as I could have included the following code for each of my random post lists:

<ul class="random-posts">
	<?php query_posts('tag=whatever&showposts=5&offset=0&orderby=rand'); ?>
	<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
	<li>
		<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</li>
	<?php endwhile; endif; ?>
</ul>

This would have been great, but the random-post ordering doesn’t work for my particular version of WordPress. As it turns out, for older versions of WordPress that are missing the incredibly useful orderby=rand parameter for the query_posts() function, there is an unofficial plugin available in the WordPress Help Forums that imparts the orderby=rand functionality to the query_posts() function, thereby enabling users of pre-2.5 versions of WordPress to implement their own random post loops.

For those of you who would like to setup some random post loops on your own site, here’s how to do it in two easy steps. (Remember, this is only necessary if the above method does not work for your particular version of WordPress.)

Numero Uno: Upload and activate the plugin

Copy & paste the following code into a file named “random-posts.php” (or whatever), upload it to your /wp-plugins/ directory, and activate it via the Plugins panel in the WordPress Admin:

<?php
/*
Plugin Name: Random Posts Query
Description: Imparts random display functionality to posts generated via 
query_posts in older versions of WordPress (especially great for version 2.3)
Author URI: http://wordpress.org/support/topic/70359?replies=3#post-444323
*/

// usage: include "random=true" as a parameter in your query_posts loop

function query_random_posts($query) {
	return query_posts($query . '&random=true');
}
class RandomPosts {
	function orderby($orderby) {
		if (get_query_var('random') == 'true')
			return "RAND()";
		else
			return $orderby;
		}
		function register_query_var($vars) {
			$vars[] = 'random';
			return $vars;
		}
}
add_filter('posts_orderby', array('RandomPosts', 'orderby'));
add_filter('query_vars', array('RandomPosts', 'register_query_var'));
?>

Numero Dos: Include and customize the template code

Once the plugin is in place, create multiple tag-specific and category-specific random-post lists by placing the following code after the main loop in your theme template file (e.g., the sidebar.php file):

<ul class="random-posts">
	<?php // use tag=whatever or category_name=whatever for cat/tag-specific posts ?>
	<?php query_posts('tag=whatever&showposts=5&offset=0&random=true'); ?>
	<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
	<li>
		<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</li>
	<?php endwhile; endif; ?>
</ul>

Before uploading, make sure you customize this code according to your needs. Old heads feel free to knock the boots, while newer chaps may benefit from the following information:

  • As mentioned in the code comments, replace the “tag=whatever” parameter with the name of the tag for which you would like to display random posts.
  • To display random posts from a specific category instead of a specific tag, simply replace the tag=whatever parameter with category_name=whatever and change the name to your chosen category.
  • Adjust the other query_posts parameters as needed to accomplish your post-display goals. For example, you may also want to display the post excerpt for each post item by including the the_excerpt() tag.
  • Note that this code is essentially the same as that given for newer versions of WordPress; the only difference being that you use the orderby=rand parameter for newer versions of WordPress (where the plugin is not required), and random=true for older versions (where the plugin is required).
  • Placing additional query_posts() loops after the main loop may result in unintended paging and/or plugin issues, so make sure to place it after the main loop.
  • To create multiple lists of random posts, simply create multiple instance of this loop and change the category or tag parameter names to suit your needs.

Time to chill

That concludes this brief retro-tutorial. Although it may not be of much use to those treading the perpetual “upgrade” treadmill, it will hopefully provide some relief for randomizing posts in older WordPress versions.

Related articles

26 Responses

  1. [ Gravatar Icon ] Teddy says:

    Very handy tutorial, Jeff! I often forget the query_posts() function such that I use conditional tags in the post loop itself - which isn’t a very good thing, I know :) Now I can specify to display posts of certain tags or from certain categories without needing to use conditional tags. Oh, and I didn’t know that the older versions of WP lacks an orderby variable, it’s nice that you’ve given some thought to those who are still using the older version (although I’d personally recommend an upgrade, if they’ve hacked the WP inside out then, well, too bad :/ ).

    You might also want to highlight that there should not be two loops on the same page - i.e. using the code in single.php and page.php, as far as I know (do correct me if I’m wrong, because I’m not that well-versed), will lead to conflict issues. This method is viable when it is used to modify the main page loop only. For other pages, it’s better to create a separate WP_query object and use it instead.

    Here is an example, a verbatim lift from a helpful page in the WP codex:

    <?php $my_query = new WP_Query('tag=whatever&showposts=5&offset=0&random=true'); ?>
    <?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
    <!-- insert other codes here -->
    <?php endwhile; ?>

    I hope I don’t sound too snooty or intrusive. I’m sorry if I sound so. I’m just trying to help, and that’s my 2 cents :)

  2. [ Gravatar Icon ] Jeff Starr says:

    Out of necessity, I have “hacked the WP inside out,” so I continue to dabble in these archaic methods. I have been using WordPress since version 1.5, and way back then, WordPress was not as “evolved” as it is today. Many functions simply didn’t exist, there was significantly less documentation, and us early adopters frequently had to hack our way around in order to make things work as intended.

    Along the way here at Perishable Press, I have implemented almost 20 working themes, each with their own special functionality, plugins, and so forth. To get everything working, I have had to hack plugins, themes, and even the core itself. Believe it or not, many of the “hacks” that have been implemented were actually needed to work around changes made to the WordPress core.

    For awhile there I did try to stay current, but many updates would break a million things on my site, so I eventually threw in the towel and decided to stick with my current version. This is not an excuse as to why I am using an older version, but rather a look at “why” staying current is sometimes more difficult than it sounds.

    For the record, I am working diligently (albeit slowly) behind the scenes on a complete overhaul that will eliminate all hacks, streamline functionality, and enable me to stay current with all the latest and greatest versions of WordPress. Run the treadmill, if you will.

    Moving on to your concerns about proper usage and multiple instances of query_posts(), the Codex makes some good points, but I have found the information provided on this topic to be somewhat oversimplified and incomplete. I don’t have the time to explain fully in this reply, but suffice it to say that query_posts() is generally safe to use for multiple loops when placed after the primary/main loop. I repeated and emphasized this information in the article, but by all means, you should probably do whatever the Codex tells you unless you really know what you are doing.

    Hopefully, I am not sounding too snooty here, although I certainly have a tendency to come across that way. ;) Just trying to explain! :)

  3. [ Gravatar Icon ] Teddy says:

    Thanks for the reply, Jeff! I guess most people proficient with PHP, database and Wordpress would have optimized their WP installation for better performance and security. I hope you didn’t misinterpret my first comment as “people who hack their WP inside out are at a disadvantage for not upgrading to the latest version of WP”.

    Yea, upgrading WP will definitely break a lot of stuff! I believe that you don’t need to upgrade to newer versions since your modified version is probably a lot faster, usable and efficient.

    I see. I’ve tested the query_loop() function again and you’re right. I encountered the conflict problem previously because I’ve placed the secondary loop ahead of the main/primary loop. Thanks for the clarification, Jeff :)

    Oh, and have a great weekend. Take care!

  4. [ Gravatar Icon ] Jennifer says:

    Very slick i my try this out on my Wordpress blog very soon I am still trying to decide on a theme at the moment but look forward to ustilizing this tag feature when i settle on one.

  5. [ Gravatar Icon ] Jeff Starr says:

    Awesome, Jennifer — thanks for the feedback :)

  6. [ Gravatar Icon ] Austin says:

    Jeff, I stumbled upon your site from the WordPress Codex, trying to figure out a way to display multiple posts from different tags/categories. You have, in roughly 4 minutes, done what I’ve been trying to do for the last 3 hours. I came up with the above idea while at work today and was all like “aw this is gonna be SWEET if it works” but couldn’t put that idea into fruition. Lo and behold, you have led me not into temptation but delivered me from the evils of code-writers-block.

    Thank you Jeff, who ever you might be, from the bottom of my heart.

  7. [ Gravatar Icon ] Jeff Starr says:

    Austin, you’re most welcome — I am glad the article helped you :)

  8. [ Gravatar Icon ] August Klotz says:

    Instead of displaying an ordinary title tag, you could do something like this:

    <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
    <?php $t = the_title('','',FALSE); echo substr($t, 0, 60); if (strlen($t) > 60) echo "..."; ?>
    </a> <? comments_number('(0)','(1)','(%)'); ?>

  9. [ Gravatar Icon ] marion says:

    I’m so glad to have found this post of yours today…I’ve been googling for the past days on how to randomized my photoblog homepage site with no luck…I still can’t believe that I’ve solved my problem by just adding ‘&amp;offset=0&amp;orderby=rand’ with the query posts() function =D

    Thank you!

  10. [ Gravatar Icon ] Jeff Starr says:

    My pleasure, marion - happy to help :)

  11. [ Gravatar Icon ] ddeconin says:

    Your different loop articles are realy interesting and I am trying to see if they can help me in my problem.

    I have an issue on my current theme where a second loop in the sidebar causes some issues with a plugin that hooks into wp_footer().

    In this case, the plugin check for is_single() and does its magic there.

    The theme’s single.php first calls sidebar.php and only then the footer.php.
    In the sidebar.php a loop is implemented over a specific category.

    By the time , the footer.php is reached then is_single() is false and is_category() is now true.

    With your experience, do you think this ‘normal’ pultiple loop behavior or is there something wrong with my theme only ?

    I tried looking in the codex , but came up empty on this issue.

  12. [ Gravatar Icon ] Jeff Starr says:

    @ddeconin: That’s interesting - I always understood WordPress to treat all associated (included) files to be part of that particular page view, such that conditionals within the sidebar, footer, and everything else would return “true” for the same thing, whether single-view or otherwise. In other words, I wonder why the footer is returning true for category when called from within a single-view template. Seems weird to me, like maybe there is something that is interfering with normal functionality.

  13. [ Gravatar Icon ] ddeconin says:

    what is happening is that there is a loop inside my sidebar.php that fetches a post from a category.
    when I add some debug code to output is_single() and is_category() I find that is_single() is true before the start of that sidebar loop and at the start of the loop it goes to false and is_category() becomes true. That remains that way so that when the wp_footer() code is executed it still has false for is_single() and true for is_category().

  14. [ Gravatar Icon ] ddeconin says:

    The loop code in my sidebar that seems to cause this is set up by calling

    query_posts(array(
           'showposts' => 1,
           'cat' => $cp_pC,
           'category__not_in' => array($ar_headline,$ar_featured),
           'post__not_in' => $ar_ID,
    ));

    I tried putting $temp_query = clone $wp_query ; in front of it , and
    $wp_query = clone $temp_query; after I finished using the loop , but it doesnt seem to work.

    I cant figure out why it doesn’t work. :-(

  15. [ Gravatar Icon ] ddeconin says:

    Ok, got a bit further. My original theme had in the sidebar the loop on cathegories and then all sidbar widgets. With this setup, and I go to a single post, in the footer is_single() resolves to true. Then I moved some of the widgets (Latest Comments, Latest Posts) to the sidebar before the cathegory loop and then is_single() in the footer resolves to false.
    So now the only question remains. How can I ‘force’ is_single() back to false?

  16. [ Gravatar Icon ] ddeconin says:

    Yes, found it, it was in the codex all along.

    http://codex.wordpress.org/Function_Reference/wp_reset_query

    So the thing to remember is :
    whenever you create a custom query, after that , call to to ‘This function destroys the previous query used on a custom Loop. Function should be called after The Loop to ensure conditional tags work as expected.’

    so, now I got to go and talk to my theme vendor about not being able to solve this ;-)

  17. [ Gravatar Icon ] Jeff Starr says:

    @ddeconin: Glad to hear you got it worked out. Thanks for documenting the process for the benefit of other readers.

  18. Woot. Thanks for this. Was a huge help.

    I implemented this on a single.php page, for to show some Random Posts from the same category. When I did this, I noticed it’d occasionally suck in the current post I was on, so I edited the query a bit, and just wanted to share it incase anyone else was looking for the same solution.

    Just added ‘post__not_in’ in the array. Simple but easy to miss if you are a newbie and don’t know what to search for.

    <?php query_posts(array(
         'category_name' => 'wallpapers',
         'showposts' => 4,
         'offset' => 0,
         'orderby' => 'rand',
         'post__not_in' => array($post->ID),
    )); ?>

  19. [ Gravatar Icon ] Jeff Starr says:

    Thanks Ricky - awesome tip! :)

  20. [ Gravatar Icon ] Fox says:

    Not sure if anyone is checking this anymore, but thought I might try.

    I’d like to sort the random posts. I know, sounds counter-intuitive, but what I’ve got is a query that pulls 2 random posts from a category (like what you have above) but I want those 2 posts to be displayed in descending order, so that the newest of the 2 random posts is above the older. Make sense? Know how I can do it? Many thanks in advance.

  21. [ Gravatar Icon ] Jeff Starr says:

    Yes someone is checking this :)

    Have you tried including the order parameter in the query? More info here:

    WP Codex: Order & Orderby Parameters

  22. [ Gravatar Icon ] Fox says:

    Many thanks for your reply! In fact I have tried using it, and I think part of the problem is that random has a hard time playing nicely with the order parameter. I used:

    <?php
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    $args= array(
         'orderby' => 'rand',
         'order' => 'desc',
         'posts_per_page' => 2,
         'category_name' => 'home-in-a-flash',
         'paged' => $paged
    );
    query_posts($args);
    ?>

    And at first I thought it was working, but upon refreshing a few times, I found my old problem (older post showing before newer post).

    Thought perhaps I might need a nested loop but not sure. Any ideas? Thanks again for your reply :)

  23. [ Gravatar Icon ] Jeff Starr says:

    I would try the same query using WP_Query, which is generally a better way of doing it. Here is an example:

    $query = new WP_Query(array(posts_per_page' => 5, 'orderby'=>'rand', 'order'=>'DESC'));
    while ($query->have_posts()) : $query->the_post();
    ...
    endwhile;
    wp_reset_postdata();

    More info here:

    http://codex.wordpress.org/Class_Reference/WP_Query

  24. [ Gravatar Icon ] Fox says:

    Thanks so much Jeff. I wasn’t successful getting it to work, but I really appreciate you taking the time to give me tips.

  25. [ Gravatar Icon ] J.Bex says:

    orderby=rand increase msql query.how to minimalize it in wordpress?

  26. [ Gravatar Icon ] john says:

    great tutorial!

    im not familiar with programming and i am confused where i should place those codes if i have a custom template also do you know if this is compatible with wordpress 3.3. I am using magazine-basic template . please, advice!!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Please use basic markup. Wrap code with <code> tags!