May 6, 2009 \\ 10:02

WordPress: Related posts by tags

As I published the last two posts here on mindBlog, the similarity in the tags i used with both entries came to my attention. Therefore I thought, it would be great to somehow link related posts together by tags they have in common. I stumbled through the web and soon found a solution to my problem. As Smashing Magazine pointed out some weeks ago, there’s an easy way to show related posts based on tags with this code-snippet:

<?php
  $tags = wp_get_post_tags($post->ID);
  if ($tags) {
    echo 'Related Posts';
    $first_tag = $tags[0]->term_id;
    $args=array(
      'tag__in' => array($first_tag),
      'post__not_in' => array($post->ID),
      'showposts'=>5,
      'caller_get_posts'=>1
    );
    $my_query = new WP_Query($args);
    if( $my_query->have_posts() ) {
      while ($my_query->have_posts()) : $my_query->the_post(); ?>
        <p><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p>
      <?php
      endwhile;
    }
  }
?>

Unfortunately this only works for the first tag of a post, for example if we’d have the tags 2009, trailer, and movie, it’ll only find all posts with 2009 as first tag! Of course this solution is unacceptable, as it limits the amount of suitable results way to much. As I found out soon, others were already complaining about this drawback, but didn’t post any solution. I don’t know why it’s even made like this, cause the WordPress-function wp_get_post_tags() already returns an array containing all tags we need, and therefore the solution is ridiculously  simple.

Solution with the new Array

So here’s mine: the query-string on line 7 already uses an array for the tags__in parameter, so why not fill this array with all the tags the current post has. tags__in can be compared to an IN-statement used by SQL, and will therefore return all posts where one of the tags fits. The only thing we need to do is to create a new array which will hold all the tag-IDs we need (tags__in only compares tags based on their ID), and pass this array to the query-string.

<?php
  //for use in the loop, list 5 post titles related to first tag on current post
  $tags = wp_get_post_tags($post->ID);
  $tagIDs = array();
  if ($tags) {
    $tagcount = count($tags);
    for ($i = 0; $i < $tagcount; $i++) {
      $tagIDs[$i] = $tags[$i]->term_id;
    }
    $args=array(
      'tag__in' => $tagIDs,
      'post__not_in' => array($post->ID),
      'showposts'=>5,
      'caller_get_posts'=>1
    );
    $my_query = new WP_Query($args);
    if( $my_query->have_posts() ) {
      while ($my_query->have_posts()) : $my_query->the_post(); ?>
        <h3><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_title(); ?></a></h3>
      <?php endwhile;
    }
  }
?>

FYI: You can see the result of this code at the bottom of every article here on mindBlog which has related posts.

Sources

Update

In case you’re facing problems by using the related posts and the comments on your page, here’s the solution. For some reason, WordPress struggles with the nested while-loop from the code above and the main-loop used to gather the entries for every page. To make sure everything goes smoothly, we simply backup the current $post object at the beginning of our code and copy it back at the end, where we also call the built in function wp_reset_query(). This should fix the issues some might have.

Here’s the complete code with the new lines:

<?php  //for use in the loop, list 5 post titles related to first tag on current post
  $backup = $post;  // backup the current object
  $tags = wp_get_post_tags($post->ID);
  $tagIDs = array();
  if ($tags) {
    $tagcount = count($tags);
    for ($i = 0; $i < $tagcount; $i++) {
      $tagIDs[$i] = $tags[$i]->term_id;
    }
    $args=array(
      'tag__in' => $tagIDs,
      'post__not_in' => array($post->ID),
      'showposts'=>5,
      'caller_get_posts'=>1
    );
    $my_query = new WP_Query($args);
    if( $my_query->have_posts() ) {
      while ($my_query->have_posts()) : $my_query->the_post(); ?>
        <h3><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_title(); ?></a></h3>
      <?php endwhile;
    } else { ?>
      <h2>No related posts found!</h2>
    <?php }
  }
  $post = $backup;  // copy it back
  wp_reset_query(); // to use the original query again
?>

More like this

We currently have

71 Responses

to this article. Want to

say something

yourself?

Leave a Reply

Comments may be held for moderation. If your comment does not appear immediately, do not repost. I reserve the right to remove any inappropriate or off-topic comments. Want other to know who you are? Register a Gravatar.

Lungau January 2011Lungau January 2011Lungau January 2011

Your Thoughts

Read what other users had to say about entries on this site. Feel free to leave your comment too.


Subscribe

Stay updated on my meandering thoughts & activities via RSS (Syndicate).


Meta