Displaying Related Posts in WordPress

There are quite a few plug-ins that are capable of displaying lists of posts that are related to the one currently being viewed in WordPress. However, sometimes they might not offer quite enough customization, or they may just be too much overhead for the features they provide.

If you are interested in displaying related posts without a plug-in, you can start with the code shown below; then customize it however you see fit. 

function get_related_posts( $howmany=2, $oPost=NULL ) {
	if( !is_object( $oPost ) && is_numeric( $oPost ) )
		$oPost = get_post( $oPost );
	if( !is_object( $oPost ) )
		return;
	if( !is_numeric( $howmany ) )
		$howmany = 2;

	$tags = wp_get_post_tags( $oPost->ID );
	if ( $tags ) {
		$tag_ids = array();
		foreach($tags as $individual_tag) $tag_ids[] = $individual_tag->slug;

		$args = array(
			'tag'		=> implode( ',', $tag_ids ),
			'exclude'	=> $oPost->ID,
			'numberposts'	=> $howmany,
		);
		$posts = get_posts( $args );
		$mr = '';
		if( count( $posts ) ) {
			$mr = '
			<aside class="related-posts">
				<h3>Related Posts</h3>
				<ul>';
			foreach( $posts as $p ) {
				$mr .= '
					<li>';
				$mr .= '
						<a href="' . apply_filters( 'the_permalink', get_permalink( $p->ID ) ) . '" rel="bookmark" title="Permanent Link to ' . apply_filters( 'the_title_attribute', $p->post_title ) . '">';
				if( has_post_thumbnail( $p->ID ) )
					$mr .= get_the_post_thumbnail( $p->ID, array( 50, 50 ) );

				$mr .= apply_filters( 'the_title', $p->post_title );
				$mr .= '</a>
					</li>';
			}
			$mr .= '
				</ul>
				<br class="clear"/>
			</aside>';
		} else {
			$mr = "\n<!-- No posts were retrieved for some reason. -->\n";
		}
	} else {
		$mr = "\n<!-- No tags were retrieved for some reason. -->\n";
	}
	return $mr;
}

function related_posts( $howmany=2, $oPost=NULL ) {
	echo get_related_posts( $howmany, $oPost );
}

This particular code will retrieve the list of tags used on the current post, then pull X number of posts from the database that use any of those same tags. It then outputs it as an unordered list. In my case, I placed these functions inside of my functions.php file for my theme. Then, I used the related_posts() function to display the list in my theme.

The usage of this particular function would be:

related_posts( clone $post, 2 );

It’s important to use the clone keyword when passing the current $post object. Otherwise, it’s possible (though not extremely likely) that the post being manipulated after the function is finished running will be different than the post that was first passed to it. Cloning that post object ensures that the original $post object is not altered in any way.

Did you like this post? Get monthly summary of our new tutorials, posts and tips to your inbox!

4 Responses

  • Allen

    nice code Curtiss! We use a related posts plugin here on HTMLCenter – but when I tried the same on CenterNetworks, it just timed out all the time – seemed like there were too many posts for it to calculate the related bits.

    does your code work better for large posting blogs?

    • I don’t have any really large blogs on which I could try it, but, unless the “tag” parameter in the get_posts() function causes an issue, I don’t see anything in the function that should take too long.

      If it still doesn’t work, one way to slim it down and optimize it a little further would be to just include the first tag from the current post in the “tag” argument for get_posts(), rather than including a list of tags. On a small blog, that wouldn’t work extremely well, because there would probably be numerous times that you’d end up retrieving only one post, or possibly no other posts that use that first tag. However, on larger blogs, I’d imagine it would work just fine.

  • Allen

    thanks Curtiss – maybe i will try it on cn this week…

  • As a wordpress developer and user I like the simplicity of your code and functionality. Adding the tags what a great idea. This will help with the search engines. I have taken a copy to test it.

Post Your Comment

Your email address will not be published.