Once in a while you write some code that you’re pretty sure will never be useful to anyone else on the planet, but the idea is cool, so you want to share it.

Hence this post.

The Power Of Relations

I was making coffee one Sunday morning, thinking about how I could keep turning a site into a wiki-level click hole, where a person could get lost for hours and days reading article after article. The reason WikiPedia works so well is that the content is all interlinked. Now, if you’ve never been a wiki editor, and you’ve just noticed that there are a billion links on every page, taking you around the universe, I’ll let you in on a secret. Those links are all human-made. A person goes in and makes those links, giving you ‘related’ posts.

But WikiPedia really only works well due to the massive amounts of people who know weird shit and are willing to help and share. When it’s just you and your crazy friend running a site, that’s a lot of work. And you have wives and pets and kids to take care of. No, you want– you need to automate the heck out of this stuff.

Related Posts are Hard

Making related posts is a hard thing. There are myriad algorithms out there to calculate ‘relatedness’ and they’re all crazy complex. Worse, they all require a lot of processing power. There’s a reason Jetpack’s related posts feature runs on their servers. They’ve got more power than you do, and it stops people on shared from being nasty neighbors.

This code is not a replacement for that code. This code is very specific and very targeted. It relies on people being clever (but not too clever). But when it works, it makes the interwoven data sets of a site work well. Because you see, we’re not talking about ‘If you like this article, read this other one…’ No. No we’re talking about crossing custom post types.

Relations Across Post Types

Hold on. I know what you’re thinking.

The point of separate post types is not to cross the streams. Yes, I know. But that’s actually not true. Menus, for example, are a post type, and you a great many people want to have specific menus to their post types. That sounds logical, doesn’t it? Well, in this case, I have a post type for TV Shows, and I have regular old blog posts.

My lightbulb moment was three-fold:

  1. When we write articles about the TV Shows, we logically use tags of the show name.
  2. Those show name tags match the slugs of the TV shows.
  3. If we link back to the articles from the TV Show page, then we’re getting people down the click hole.

This meant my logic was simple: On the TV show page, check if there are any blog posts tagged with the show name and, if so, that post was ‘related’ to the show and therefore we should link back to it.

The Code

I put all this into a function so I could re-use it in a couple places. I like not repeating myself with code. I also have the function call another function, because I actually re-use this to connect different post types that all use the same tags. If you don’t need that, you can tighten it up.

The Display

This is in the theme:

$slug = get_post_field( 'post_name', get_post() );
$term = term_exists( $slug , 'post_tag' );
if ( $term !== 0 && $term !== null ) { ?>
	<section name="related-posts" id="related-posts" class="shows-extras">
		<h2>Related Posts</h2>
		<?php echo related_posts( $slug, 'post' ); ?>
	</section> <?php
}

The Functions

And here’s the function it calls:

function related_posts( $slug ) {
	$related_post_loop  = related_posts_by_tag( 'post', $slug );
	$related_post_query = wp_list_pluck( $related_post_loop->posts, 'ID' );

	if ( $related_post_loop->have_posts() ) {
		$the_related_posts = '<ul>';
		foreach( $related_post_query as $related_post ) {
			$the_related_posts .= '<li><a href="' . get_the_permalink( $related_post ) . '">' . get_the_title( $related_post ) . '</a> &mdash; ' . get_the_date( get_option( 'date_format' ), $related_post ) . '</li>';
		}

		$the_related_posts .= '</ul>';
	}

	return $the_related_posts;
}

And here’s the function that calls:

function related_posts_by_tag( $post_type, $slug ) {
	$term = term_exists( $slug, 'post_tag' );
	if ( $term == 0 || $term == null ) return;

	$count = '5';
	$query = new WP_Query( array(
		'post_type'       => $post_type,
		'posts_per_page'  => $count,
		'no_found_rows'   => true,
		'post_status'     => array( 'publish' ),
		'tag'             => $slug,
		'orderby'         => 'date',
		'order'           => 'DESC',
    ) );

	wp_reset_query();
	return $query;
}

The Result?

An unordered list of the last five related posts. You could add a link to ‘show more’ if you were so included.

Reader Interactions

%d bloggers like this: