› Displaying Related Posts without a Plugin in WordPress

Displaying Related Posts without a Plugin in WordPress

Use WP_Query to fetch a list of related content by category

Email this to someoneShare on Facebook0Share on Google+0Share on LinkedIn0Share on Tumblr0Share on StumbleUpon0Tweet about this on TwitterShare on Reddit0Pin on Pinterest0

As I’m writing this, a plugin search on WordPress.org for “related posts” yields 1,328 results. It’s not quite a googol (OK, not even close), but it’s clear there’s no shortage of such plugins available in the repository. Despite this, I haven’t ran across one I’m fully satisfied with (I’m working on my own, but that’s a different story). And if you’re here, reading this, I suspect you haven’t either.

This is why I prefer to use my own code for fetching and displaying related posts, on both mine and my clients’ websites.

This tutorial will guide you through the process of writing your own related posts code. Let us begin!

Part I. – Pre-Query Checks

First up is building the instance of WP_Query that we’ll use to retrieve the posts. But before we do that, we need to establish what we’re looking for. The following assigns an array of get_the_category() to a variable.

$cats = get_the_category($post->ID);

Next, we want to make sure that’s valid before trying to do anything else, so we’ll run:

if ( $cats == true ) {
	$cat_id = array();
	foreach ( $cats as $cat ) { 
		$cat_id[] = $cat->term_id;
		}

This makes sure $cats is valid, and then casts it as an array. Next we run a foreach loop, which moves our previously retrieved category IDs into the array. This will help us fetch content in the same category with our WP_Query instance.

At this point, we’ve assembled enough information about the currently queried object to determine what should be displayed as a related post, so we’ll move on to the query.

Part II. – Building the Query

When we create a new instance of WP_Query, we can pass arguments, which we use to build our query. Since we only want to retrieve a few posts, namely those residing in the same category as our current posts, we’ll define our arguments as follows:

$args = array (
		'category__in' => $cat_id,
		'post__not_in' => array ( $post->ID ),
		'posts_per_page' => 3
	);

The first parameter, category__in, lets us tell our instance of WP_Query which categories our query should return posts from. We pass our previously defined variable of $cat_id, which contains an array of the IDs relating to the category of our current post.

Next, the post__not_in parameter accepts an array of IDs. To it, we pass the current post ID. This is done to make sure we don’t display the current post in our list of related posts.

The last parameter is the posts_per_page, which lets us set the number of posts to return. We’ll use three posts in this example, but feel free to customize it to suit your needs.

I recommend browsing through the WP_Query codex page if you’re looking for additional options here.

Finally, we’ll create our instance of WP_Query, pass our arguments, and assign it to our custom name, $related_query:

$related_query = new WP_Query( $args );

Part III. – The Loop

Now we’re set to build The Loop that we’ll use to actually retrieve and display the posts. If you aren’t familiar with The WordPress Loop, have a look at the codex page for a refresher.

Now we’ll be using the custom instance of WP_Query we created earlier to interact with the loop:

<?php
if ( $related_query->have_posts() ) {
	while( $related_query->have_posts() ) {
		$related_query->the_post();
		}
		}
		?>

This gives us a starting point for working with and displaying our related content, but we still have a bit of work to do.

First, if our query returns posts, we want to create a container for them, which in this case will be the opening tags of a generic content div, an opening unordered list tag, and a simple heading title.

<?php
if ( $related_query->have_posts() ) { ?>
	<div>
		<h3>Related Posts</h3>
		<ul>
	<?php } ?>

Now we need to determine the appropriate action while there are posts, with which we’ll define our list tags (to wrap around the posts):

<?php
	while( $related_query->have_posts() ) {
		$related_query->the_post(); 
		?>
		<li>
		<?php 
			the_title();
			the_excerpt();
			?>
		</li>
<?php 
		}

At this point, we’re outputting list tags along with the title and excerpt from each related post. It’s functional, but hardly useful. So let’s spruce things up a bit by adding hyperlinking each post title and adding a thumbnail:

<?php
	while( $related_query->have_posts() ) {
		$related_query->the_post(); ?>
		<li>
			<a href="<?php the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>">
			<?php the_post_thumbnail( 'thumbnail', array ( 'class' => 'alignleft' ) ); ?>
			</a>
				<strong>
					<a href="<?php the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>">
						<?php the_title(); ?>
					</a>
				</strong>
				<?php the_excerpt(); ?>
		</li>
<?php 
		}

The call to the_post_thumbnail() is the only thing I’ll go over here, as the other attributes are fairly generic. The first parameter we’re using in the_post_thumbnail() is the size, and this can be changed to medium, large or full. The second parameter we’re passing is a class within an array. Here we’re passing the WordPress generated class alignleft, which essentially floats the thumbnail to the left. Further reading on the WordPress Codex is recommended if you want to make additional modifications to the thumbnail display.

Now, immediately following our closing bracket for our while call to have_posts() let’s echo the HTML to close out our opening elements. Don’t forget the closing bracket to wrap up our loop.

<?php
echo '</ul></div>';
}

And finally, after The Loop, let’s call wp_query_reset() to make sure we restore the query and postdata.

<?php
wp_reset_query();

Part IV. – Putting it all Together

Now we should have working code. Let’s add some CSS selectors and see what it looks like wrapped up in a nice little functional package:

<?php
/* Fetches list of related posts */

// gets the current categories
$cats = get_the_category($post->ID);

if ( $cats == true ) {
	$cat_id = array();
	foreach ( $cats as $cat ) { 
		$cat_id[] = $cat->term_id;
		}
	
$args = array (
		'category__in' => $cat_id,
		'post__not_in' => array ( $post->ID ),
		'posts_per_page'=> 3
	);
	
$related_query = new WP_Query( $args );
if ( $related_query->have_posts() ) { ?>
	<div id="related-posts">
		<h3>Related Posts</h3>
		<ul>
	
<?php
	while( $related_query->have_posts() ) {
		$related_query->the_post(); ?>
		<li class="related-content">
			<a class="related-title" href="<?php the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>">
			<?php the_post_thumbnail( 'thumbnail', array ( 'class' => 'alignleft' ) ); ?>
			</a>
				<strong>
					<a class="<?php post_class(); ?>" href="<?php the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>">
						<?php the_title(); ?>
					</a>
				</strong>
				<?php the_excerpt(); ?>
		</li>
<?php 
		}
echo '</ul></div>';
}
}
wp_reset_query(); 
?>

I’ve given our container container an ID of related-posts, our list items a class of related-content and our linked titles a class of related-title. We’ll use these selectors to apply some basic styles in the next section.

Part V. – Adding CSS

Without CSS, our related posts look like crap — so let’s remedy this by adding some basic styles.

First, we’ll apply a clearing attribute to properly separate our list items, as well as a display property for formatting:

li.related-content {
	clear: both;
	display: table-row;
	}

Then a border and a bit of padding for the container:

#related-posts {
	padding: 10px 20px;
	border: 1px dashed #333;
	}

If you want to use this code in your template, save the final code from Part IV into a file called related.php (or whatever), and then call it within your theme’s single.php as follows:

<?php get_template_part ('related'); ?>

Feel free to customize the CSS as you see fit. And please comment below if you need additional help or clarification.

Subscribe for weekly tutorials