I’m a big fan of randomness. I mean in the web sites I build- they introduce variety to the experience (e.g random blog headers) or to the experience. Something I have rolled into most of my syndicated connected course type sites is a little custom template code that allows me to have links that can redirect the site visitor to a random blog post from the pile of syndicated posts.

Why?

Because I can? partly.

Usually it’s rolled into a place where I talk about commenting. A challenge for people is picking which post out of 50, 200, 1200… they should comment on. A random picker seems like it works. This is my usual approach, and is based upon creating a category hierarchy for the syndicated content (see the details on this on part 2 of my Feed WordPress 101 series).

I set up Feed WordPress to add a category of “Syndicated” to every syndicated post (or sometimes O use one called “Flow”, and then create sub-categories below that that are applied to different blog feeds. For my current project at DML Commons the category structure for syndicated content is:

For the Random Post Spinner Thingamgic, we do not want random from all posts on the site, but within this category structure.

The first thing to put this in action calls for adding code to the functions.php file (yes, this technique requires theme hacking). And before you modify any themes file, consider first making use of a Child Theme.

So in your functions.php we need something that will allow us to send a variable to our random gizmo, one that will tell it what category in the tree above to pick from. We pass the variable through appending to the url something like ?c=booger where we pass the script a variable that says find a random post in the “Booger” category (the variable that is passed is the category “slug” or the short name used for it when it is part of a URL.

This is what goes into functions.php (if this is the first thing you add to a child theme, well you have to create a blank file, and wrap its contents in PHP code tags).


/* ----- add allowable url parameter for urls */
add_filter('query_vars', 'dmlhub_parameter_queryvars' );

function dmlhub_parameter_queryvars( $qvars )
// allow  parameters to be passed in wordpress query strings
{
	$qvars[] = 'c';			// when we need to pass a category
	return $qvars;
}

When we use add_filter it creates a placeholder in the WordPress logic that says “when we deal with the part of wordpress that deals with query variable, call our custom function dmlhub_parameter_queryvars ) I try to name my custom functions with a prefix to make it unique to my code).

And this little function lets WordPress deal with a c=XXXXXXX in the URL. It does not do anything with the info yet, but it lets it get passed inside of WordPress.

Next I create a WordPress Page called “Random”. I put nothing in it. Boring. But my creating a file in my child theme called page-random.php it gets used rather than the general page.php template only for the page with a slug name of “random”.

And so page-random.php can contain any code I want it to have, and is called only for a URL on my site http://www.mygroovysite.com/random. This is what goes inside:

< ?php
/*
Random Syndicated Post Picker
Use on page with slug 'random' to send viewer to random post optionally, within category
*/

// define slug for default category if none provided
$default_category = 'blogs';

// used category passed; otherwise default is category for all syndicated blog posts
$incat =  (isset($wp_query->query_vars['c'])) ? $wp_query->query_vars['c'] : $default_category;

// set arguments for WP_Query on published posts to get 1 at random
$args = array(
    'post_type' => 'post',
    'post_status' => 'publish',
    'posts_per_page' => 1,
    'category_name' => $incat,
    'orderby' => 'rand'
);

// It's time! Go get a random post from the database
$my_random_post = new WP_Query ( $args );

while ( $my_random_post->have_posts () ) {
  // redirect to the random post
  wp_redirect ( get_permalink () );
  exit;
}
?>

I first define a category to use if none is passed through new new parameter. The value is the lowercase shortname or slug for the category, in this case the most common random thing I will do is generate a link to a random syndicated blog post via http://dmlcommons.net/random.

The defining statement sets the variable $incat to whatever was passed in the c= part of the URL; if none was provided it stays as the default category. Wow, a flaw of my code is there is no trap if the value of c= does not correspond to a real category. Tough luck. If you manually type in the wrong name you are screwed.

Then we set up the arguments ($args) used to set the right query on the database, we only want posts (not pages), that are published (not drafts), only 1 of them, and from within a specific category, and the magic thing, sort the results randomly- pick 1 post randomly from all of the rest (note that I have seen web hosts such as WP Engine where, in the interesty of optimization, MySQL has been configured not to use sorting results randomly).

We walk through all the results (all one of them), and use the function that gets the posts “permalink”, and a command that redirects the viewer to that URL (wp_redirect). Note that FeedWord Press, if set to link to the original post, will return that external post URL as the value for the permalink.

And that works, try http://dmlcommons.net/random to get a random syndicated blog post, or http://dmlcommons.net/random/?c=dr for a random synidcated Design Research syndicated blog post, or even http://dmlcommons.net/random/?c=twitter for a random syndicated tweet.

And there you go.

Well except for Ken

That is a good question. Because once you are a few weeks, months into a course, maybe you do not want random reaching back to the very first weeks. Maybe you want more currency.

I have thought about this before, at one time I might have had the ds106 random posts set to use the last two weeks as a window to fetch from (leading to other issues when the course ends).

This turned out to be not all that hard to do. My solution is to provide another URL parameter to specify, optionally how many days back in time to look for a random post. So we add a line to our query parameters thing in functions.php to provide use of a parameter d= (yeah, cryptic URL parameters, sue me. Or make your own names).


/* ----- add allowable url parameter for urls */
add_filter('query_vars', 'dmlhub_parameter_queryvars' );

function dmlhub_parameter_queryvars( $qvars )
// allow  parameters to be passed in wordpress query strings
{
	$qvars[] = 'c';			// when we need to pass a category
	$qvars[] = 'd';			// when we need to pass day offset
	return $qvars;
}

And the code for the page template has some extra parts to deal with this:

< ?php
/*
Random Syndicated Post Picker
Use on page with slug 'random' to send viewer to random post optionally, within category
specified by parameter c={slug}and also by d={number of days to restrict search}
*/

// define slug for default category if none provided
$default_category = 'blogs';

// used category passed; otherwise default is category for all syndicated blog posts
$incat =  (isset($wp_query->query_vars['c'])) ? $wp_query->query_vars['c'] : $default_category;


// set arguments for WP_Query on published posts to get 1 at random
$args = array(
    'post_type' => 'post',
    'post_status' => 'publish',
    'posts_per_page' => 1,
    'category_name' => $incat,
    'orderby' => 'rand'
);

// do we have a number of days to restrict to (last X days)
$days_before =  (isset($wp_query->query_vars['d'])) ? $wp_query->query_vars['d'] : 0;

if ( $days_before )  {
	$args['date_query']  = 
		array(
        'column'  => 'post_date',
        'after'   => "-$days_before days"
   		);
}

// It's time! Go get a random post from the database
$my_random_post = new WP_Query ( $args );

if ( $my_random_post-> have_posts() ) {
	while ( $my_random_post->have_posts () ) {
  
	  // redirect to the random post
	  wp_redirect ( get_permalink( $my_random_post->post->ID ) );
	  exit;
	}
} else {
	die('Egads, we could not find any random posts!');
}
?>

What we do is an extra check for a d= parameter to get the number of days to look backward in time, and if a value like d=7 is used, we add to the arguments array a construct that says to look for posts after 7 days ago in time (a time value of – 7 days).

Because we might not get any results, I added a conditional that returns an error message if no random posts would be found.

This appears to be working for the DML Cmmons site, examples:

And that is how we had some time ranges to the random spinner. Some may want a more specific time range, e.g. “the week of February 3, 2015”. This is doable, yes, but… well “left as an exercise to the reader”.

Spin on!


Public Domain Pixabay Image by MirellaST http://pixabay.com/en/roulette-game-gaming-money-colors-252390/

The post "Random WordPress Posts With a Time Twist" was originally pulled charred and crispy from a smoky charred oven at CogDogBlog (http://cogdogblog.com/2015/04/random-posts-time-twist/) on April 10, 2015.

4 Comments

  • Ken Bauer

    Oh how do I love this and deeply appreciate Alan’s drive to take a good idea and then just put it into practice.

    This is an example that i can use when I explain to my students (or faculty and administrative colleagues) what “scratching an itch” means in the context of open source as so well stated by Eric S. Raymond in The Cathedral and the Bazaar” as the first lesson in this book everyone in education should read:

    1. Every good work of software starts by scratching a developer’s personal itch.

    I guess I provided that itch on April 9th or perhaps just re-manifested an existing itch which led to Alan pulling out the backscratching keyboard to alleviate it.

    Of course this inevitably leads to the creation of more work (itches that need to be scratched), I think my list includes:

    Rolling some of these pieces into a plugin. There are so many of these tweaks that Alan (and others I guess) have put together into custom theme hacks that work really well. Putting this into a plugin requires a little bit of coding (but not much since the code is there) but mostly refactoring the code to become generic and then wrapping it into some exposed settings code in the WordPress admin dashboard.

    My background is computing science where I received my B.Sc. (1993, University of Victoria with Honours), M.Sc. (1995, University of Washington), and a pursued-but-left-at-ABD Ph.D. (2005-2013 University of Alberta). My time in that field exposed me to the greats in software development and in particular those in the community around OOPSLA (Object-Oriented Programming, Systems, Languages and Applications) conference at which I was a conference committee member from 1995-2007.

    I digress, so the point I’m trying to make is that there are so many parallels to good software and good education. A quick check shows that I have three pending blog posts (posts sitting in Draft mode) and probably more that are in my head but not yet injected into my blog.

    I think my summer schedule is filling up with various itches to be scratched.

    • Alan Levine aka CogDog cogdogblog.com

      Scratch away! I should start at the plugin writing approach, have looked enough at their coder to know what they are doing.

      And you have way more CIS chops than me, a measly CIS minor in 1986.

  • Ken Bauer

    So, I wanted to get this going again on my course blogs to encourage students to read other posts of other students…. and maybe comment.

    * Find this post through searching the cogdogblog, yay.
    * Oops, need to create that child them. Check.
    * Copy code locally, sftp to my ReclaimHosting setup
    * Doesn’t work, something broken
    * Send out the Cogdog signal… call in help from @ReclaimHosting
    * Profit.

    Details at:
    https://twitter.com/ken_bauer/status/773164734707302401

  • Alan Levine aka CogDog cogdogblog.com

    I’m fixing the code posted here as I type.

    Line 42. It figures.

Leave a Comment

All fields are required. Your email address will not be published.