0

I'm using the get_categories template tag to display a list of categories in a sidebar widget. I would like the widget to display a completely random selection of categories on each page load. I realize I can use the orderby=>rand parameter but my understanding is that this only rearranges the order of the fetched categories.

For example, if I have 100 categories and want to display 5 categories I could have the number parameter set to number=>5 and orderby to orderby=>rand but this would fetch the same 5 categories each time and only rearrange the ordering of those categories. Is that how it works?

I found the following code snippet:

$cats ='';
$categories=get_categories();
$rand_keys = array_rand($categories, 5); // 5 is the number of categories you want
foreach ($rand_keys as $key) {
    $cats .= $categories[$key]->term_id .',';
}

Is it necessary to use something like this to get a completely random selection of posts?

  • you could assign a number to each category and get a rand number, but it gets tricky, because a random number is something complex, you could get the same number 7 times in a row and its still considered random =[, i am curios about the solution for this. – David Lee Mar 24 '17 at 0:18
  • @jrcollins it is not necessary to obtain a random selection of categories in order to retrieve a random selection of posts. So do you want a random selection of posts, or a random selection of categories? – bosco Mar 24 '17 at 0:30
  • I want to show a random selection of categories, not posts. – jrcollins Mar 24 '17 at 1:08
2

Sadly get_categories() and get_terms() won't likely ever support 'orderby' => 'rand' which really leaves you with two options - get every category and select 5 randomly, or construct your own WP_Query to query categories with 'orderby' => 'rand'. The former is easier to implement, and will likely have better performance (unless you have an very large number of categories, perhaps).

So for your purposes, the following would suffice:

$categories = get_categories();
shuffle( $categories );
$categories = array_slice( $categories, 0, 5 );

After which $categories would contain 5 randomly selected categories.

Technically, the rand_keys() approach is slightly faster. But in practice the difference is negligible (we're talking nanoseconds), unless you're working with hundreds of thousands of categories.

It's worth noting that if your WordPress installation doesn't contain at least 5 categories the above code will throw an error (as would the snippet in your question), since you cannot take the first 5 elements of an array that's only say 3 elements long.

You could improve upon it by throwing it into a function to make it reusable and more flexible, and adding a couple checks to help avoid potential errors:

function get_random_categories( $number, $args = null ) {
  $categories = get_categories( $args ); // Get all the categories, optionally with additional arguments

  // If there aren't enough categories, use as many as possible to avoid an error
  if( $number > count( $categories ) )
    $number = count( $categories );

  // If no categories are available or none were requested, return an empty array
  if( $number === 0 )
    return array();

  shuffle( $categories ); // Mix up the category array randomly

  // Return the first $number categories from the shuffled list
  return array_slice( $categories, 0, $number );
}

With that function loaded, you could simply call $categories = get_random_categories( 5 ); to obtain an array containing 5 random categories - and if the installation has fewer than five categories in total, it would simply return as many as are available, in random order.

Obtaining random posts is much easier, as you can simply use the 'orderby' => 'rand' argument, as you mentioned - when omitting taxonomy and category arguments, a query will return posts from all categories by default.

  • Thanks for the answer. So, what exactly is the advantage of this method compared to using the rand_keys() approach? Also, could explain the $number variable? – jrcollins Mar 24 '17 at 4:33
  • There's really no advantage - it's just easier to write and understand. But no big disadvantage, either. The $number argument is just for the sake of making it a more flexible function which can return any desired number of random categories. The two if() conditionals just catch things which might cause errors - you can't return the first 5 elements of an array which only has 3 elements in it, for example. In a similar manner, in the snippet in your question, array_rand() would throw an error if the WordPress installation it was used in doesn't have 5 categories in the database. – bosco Mar 24 '17 at 4:48
  • So for your purposes, you could call get_random_categories( 5 ) to retrieve an array of 5 random categories. If you were so inclined however, you could take the logic out of the function, remove the $args variable, remove the two ifs, and replace $number in the array_slice() call with 5 - it should function just as well, so long as you have at least 5 categories in your database. – bosco Mar 24 '17 at 4:50
  • I added this info to the answer, hope it clears things up =] – bosco Mar 24 '17 at 5:00
  • So, I would need to define $number as the number of categories I want to display? For example, $number=5 if I wanted to display 5 categories? – jrcollins Mar 24 '17 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.