There are several articles out there on how to add WordPress related posts without using a plugin. I’m adding one more to the fray only because all the other posts do one thing; they match related posts based on those posts being in the same category or having the same tag as the current post. If you’d like to match posts based on that criteria (same category, same tag), these are well-written articles:
By Darren, on Hongkiat here http://www.hongkiat.com/blog/wordpress-related-posts-without-plugins/
By the staff at WpBeginner http://www.wpbeginner.com/wp-tutorials/how-to-display-related-posts-in-wordpress/
If you’d like to do more than that, I share here how to match against title and post content and provide a fallback that matches against category. On to the code:
First off, your theme will need to have thumbnail support. Add this to your functions.php (most themes already have this )
add_theme_support( 'post-thumbnails' ); //Important //set_post_thumbnail_size( 100, 50, true ); //If the default WordPress thumbnail dimensions of 150 x 150 won't cut it for you, use this to change them
Then, add these three functions to, well, functions.php
/** * Append related posts to the bottom of the post * currently being displayed * @since 1.x.x */ function yourthemename_get_related_posts($content){ global $wpdb,$post; $related_posts_title = __("Highly Recommended:"); $number_of_related_posts = 3; //First, we match content based on post title and post content $matchContent = addslashes($post->post_title. ' ' . $post->post_content); //Query your Database to pick the related posts. Note that we don't use SELECT *, which is inefficient $sql = "SELECT ID,post_title FROM ".$wpdb->posts." WHERE MATCH(post_title,post_content) AGAINST ('".$matchContent."') AND post_status = 'publish' AND ID != '".$post->ID."' LIMIT ".$number_of_related_posts.";"; $related_posts = $wpdb->get_results($sql); $content .= ' <div class="related_posts">'; $content .= ' <h3>'.$related_posts_title.'</h3> '; $content .= ' <ul>';</ul> //If matching title/content didn't pick-up a thing, we fall-back to querying based on same category if( empty( $related_posts ) ){ $category = get_the_category(); $cat=$category[0]->cat_ID; $args = array( 'posts_per_page' => $number_of_related_posts, 'cat' => $cat, 'post__not_in' => array($post->ID) ); $related_posts = new WP_Query ( $args ); if ( $related_posts->have_posts() ) { while ( $related_posts->have_posts() ) : $related_posts->the_post(); $content.=yourthemename_wrap_related_post_item(get_the_ID(),get_permalink(),get_the_title()); endwhile; } } else { foreach ( $related_posts as $relatedPost ) { $content.=yourthemename_wrap_related_post_item($relatedPost->ID,get_permalink($relatedPost->ID),$relatedPost->post_title); } } $content .= ' '; $content .= ' </div> <!--.related_posts-->'; wp_reset_postdata();//Important to allow the comments template to show comments. Without this, comments won't display //The comments template relies on the global $wp_query object to be set for it to work; We call this function to set the post data back up return $content; } /** * The layout for an item in related posts. We create this separately since * the items are populated using two different approaches [matching against post title/content and * matching against same category * * @param $id The post ID * @param $the_permalink The post permalink * @param $post_title The post title * @return An HTML li element * @since 1.x.x */ function yourthemename_wrap_related_post_item($post_id,$the_permalink,$post_title){ $content=''; $content .=' <ul> <li class="related-post">'; $content .= '<a title="Permanent Link to '.$post_title.'" href="'.$the_permalink.'">'; $content .= yourthemename_the_post_thumbnail(); $content .= '</a>'; $content .= '<a title="Permanent Link to '.$post_title.'" href="'.$the_permalink.'">'; $content .= ' </a> <h4>'.$post_title.'</h4> '; $content .= ' '; $content .='</li> </ul> '; return $content; } /** * Returns a string containing an HTML image element for the post currently being displayed * or a default image if no thumbnail is defined (Which happens when the post doesn't have a 'Featured image' * @since 1.x.x */ function yourthemename_the_post_thumbnail(){ if ( has_post_thumbnail() ) { // check if the post has a Post Thumbnail assigned to it. return get_the_post_thumbnail($post_id,'thumbnail'); } else{ return '<img class="attachment-thumbnail wp-post-image" src="'.get_stylesheet_directory_uri().'/images/yourtheme_default_thumbnail.jpg'.'" alt="yourtheme_changeThis" width="150" height="150" />'; /*Your theme's default thumbnail*/ } }
The code has quite a number of comments for you to follow what’s going on. WordPress has coding standards; all efforts are made to ensure that the code conforms to them.
When you copy the code, replace all instances of yourthemename with your theme’s actual name.
Particular spots you need to customize:
Change $related_posts_title = __(“Highly Recommended:”) and $number_of_related_posts = 3 to suit your needs
Very important: Change yourtheme_default_thumbnail.jpg to the name of an actual image in your theme’s image directory. Make sure its dimensions are the same as the thumbnail dimensions (re-sizing by CSS is bad, very bad)
Then, the CSS:
.related_posts{ width: 100%; } .related_posts ul { margin: 0; padding: 0;} .related_posts ul li {list-style-type: none; float: left; padding: 1em;} .related_posts ul li:hover { background-color: #CCC;}