54 Comments
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
?>












thanks for the code, this is just what i’ve been looking for.
however, when its enabled, it messes up the comments that follow (i.e. the comments shown are from a different post, not the one above it)
any idea how to fix this? i’ve temporarily disabled the code to prevent confusion to my readers.
thanks in advance
sorry, forgot the link (the code is still in the single page template for you to view via source), for example:
http://www.boilr.net/2009/05/03/clean-your-lcd-hdtv-with-anti-static-monitor-wipes/
now, it appears to be blocking all comments (the link has 1 comment at the time of this posting) from showing as opposed to showing the wrong comments.
thanks again
p.p.s.
sorry, the code, even after i it was blocking comments. here is what i had inserted:
ID);
$tagIDs = array();
if ($tags) {
echo ‘Related Posts’;
$tagcount = count($tags);
for ($i = 0; $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(); ?>
<a href=”" rel=”bookmark” title=”">
last comment, i swear!
hm, this code seems to be missing all the < ?php ?> statements? don’t know if you copied it wrong, or it’s a problem with the commenting-function on my side.
i can’t see where you inserted the code by looking at the source of your page. if you want to, email me your complete file single.php (the one where you inserted the code), and i’ll have a look at it and reply back to you shortly.
this is my account: klemm.michael[at]gmail.com
i emailed it to ya just a minute ago. thanks so much for the code and for trying to help me fix it.
also, great site!
cheers
i had a look at your code and sent you a version with some minor changes.
report back to me if it made any difference on your site, can’t try it here.
i updated the post above with a fix for the comments-issue.
hope that will help you.
3mind, thanks so much for the update, works perfectly! I’ll definitely be sharing this great code, with credit to you of course!
[...] to the awesomeness that is WordPress and the useful code (and help) from 3mind, Boilr proudly presents its latest upgrade – Related Posts. (note: a plugin-free solution, for all [...]
Great work thats what i was looking for. specially the thing with the comments
danke :)
I had been looking to update one of my free themes with this function and was unable to get around using the first tag. Your solution works perfectly! Thank you!!! :D
Thanks for this one, it’s exactly what i was looking for :)
[...] problem appeared when I used the ‘related post’ script in my single post page. Luckily 3mind.at has already created a nice solution, so thanks guys. addthis_pub = ‘markknol’; Tiny URL [...]
very GOOD!!! =)
Thank you very much! Great example. If you’re ever on the IU campus in Bloomington, Indiana, USA, look me up, I’ll buy you a beer.
[...] had actually gotten the code here. I re-visited his site this morning and found that the code had been updated since my initial visit [...]
i use PHP to restore my comments table ! :S FUCK! jajaja but here is the fix !
thank you to resolve the problem with comments, now it’s work great !!!
thanks!
Hi there,
thanks for this code. I was wondering whether it is possible to display related posts but only from specific categories. I’ve added a cat_ID to the $args but this doesn’t seem to work.
ID);
$tagIDs = array();
if ($tags) {
$tagcount = count($tags);
for ($i = 0; $i term_id;
}
$args=array(
‘tag__in’ => $tagIDs,
‘post__not_in’ => array($post->ID),
‘showposts’=>5,
‘caller_get_posts’=>1,
‘cat_ID’=>24
);
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<a href=”" rel=”bookmark” title=”">
Any ideas on this, I would greatly appreciate any help on
thanks!
hey,
that should be possible by using ‘cat’=>24 , instead of ‘cat_ID’.
also be sure that the category-number does exist.
if you want to look up more than one category there’s a ‘cat__in’ parameter as well.
is you need any further help on this one let me know, didn’t try it myself yet, but that should do the trick for your problem.
Hi there,
I adjusted the ‘cat’ but it doesn’t seem to pull through the entries. And if I employ ‘cat__in’=>24 it pulls through all related posts irrespective of whether they are in cat 24 or not.
Any ideas? I really appreciate your help on this
cheers
Jon
PS – Cat 24 does exist by the way!
hi again,
i was able to get it to work with the following steps…
first i retrieve all the categories of the current post, similar to the tags function:
$cats = wp_get_post_categories($post->ID);
now, I use the first category ID of the array as ‘cat’ parameter:
$args=array(
‘cat’ => $cats[0],
‘post__not_in’ …
that did the trick for categories. please be aware that the code does only look up the first category, for some reason the cat__in parameter which would take an array as argument doesn’t work.
you’ll also have to remove the ‘tag__in’ part of the query, as both together don’t seem to work either.
That’s exactly what I need to do but I tried popping that code in and it isnt working. Not sure if I have done it right. Could you post the snippet of code that works for just the one specific category please. would be amazing if you oblige. thanks,.
To clarify, isnt the code you just provided, displaying related posts to the category the post is filed under?
I would like to display related posts from a category with a specific id regardless of what category your in. eg
your in the main blog and it displays: related posts from category id = 8
hm, did you try
$args=array(
‘cat’ => ’8′,
‘post__not_in’ …
?
Spot on, can’t thank you enough!
Thanks for that snippet! I tried nearly every related/similar posts plugin out there and other than your solution none really worked. The only thing I would love to have is a separator between the related posts; just like the_tags provides as second parameter.
If I use just a plain comma it would output: “post1, post2, post3,” including a bad looking comma at the end of the row.
Any chance for a separator only *between* the titles?
Thanks, Michael
well, that’s more a php-related question you have.
you could try to add something like an < ?php if ... statement inside within the while loop which checks the $my_query->have_post() result. if it’s true, add a ‘,’, otherwhise do nothing.
hope that helps.
I decided for another way; I display only one related post now but with its main image as teaser (through the Get The Image Plugin). Looks fine :) But thanks for the help anyway.
Thank you so much :)
Thanks for the code, it works great!
Is there a way to modify it to show something like ‘No Related Posts Found’ if there aren’t any posts sharing the same tags? I tried to do it myself by adding an else statement, but failed miserably.
Any tips would be greatly appreciated. Thanks again!
yeah, sure it is.
please see the edited lines at the bottom of the last code example above!
regards
Works like a charm. Thanks for the quick response!
Hello, the code its works great!
I wonder how to make the post with an image showing that it contains?
This is how you do it on your blog!
You can post this code?
Best Regards
Thanks man. This was perfect for me. I definitely agree the way it was originally written doesn’t make a bit of sense. Especially since tags are alphabetized.
glad i could help!
Hi, if no related posts are found should it not be diplaying “No related posts found” or am i just reading the code wrong.
yes, that’s what it should display.
Thanks a lot.. I was looking for a plugin, but now m gonna try this one.
Great work.. keep it up..!!!
Thank you! Works great!
This can further be optimized by using the ‘fields’ arg for the wp_get_post_tags() function so the for loop becomes obsolete like so:
$tags = wp_get_post_tags($post->ID, array('fields'=>'ids'));
if ($tags) {
$args=array(
'tag__in' => $tags,
'post__not_in' => array($post->ID),
'showposts'=>5,
'caller_get_posts'=>1
);
$my_query = new WP_Query($args);
....
Darf ich das Skript direkt in eines meiner Themes einbauen (100% GPL) – Das Skript läuft super und ich muss da Rad ja nicht neu erfinden!
ja, vielleicht ein comment mit // http://www.3mind.at im source und ich hab kein problem damit!
Klasse … besten Dank, den Comment bekommst du natürlich!
[...] ini bukan 100% kode murni saya yang salah saya cuplik dari sini dan sini, saya hanya memodifikasi sedemikian rupa sehingga lebih nyaman aja secara saya. Dan patut [...]
AWESOME piece of code
been using it on lots of blogs, without any problem so far, except on one of my blogs, where it seems to show lots of duplicated posts…
maybe it has to do with having lots of posts with same tags over and over, but is there a way to prevent that from happening?
thanks
Hm, I’m not totally sure what you’re trying to explain.
Do you have posts that have one and the same tag multiple times? Didn’t even know that’s possible with WordPress (doesn’t really make sense either).
If you can provide me with an exact example we can try to figure out the issue and if possible a solution.
BR
3mind, here you can see what’s going on… http://democraciachina.com.ar/2010/02/silencio-por-favor/ there are two posts repeating on similar posts…
thanks
Excellent, thank you…you fixed the issue of only showing related posts to the fist comment…I have another issue with is and no one else seems to have the same problem.
I am having an issue with the Pagebar plugin. The pagebar is displayed directly underneath the related posts in each post. How do I go about removing this?
Or is there a good pagebar code without a plug-in? Any help would be appriciated…thanks again!
Thank you, this is excellent.
Just wondering if there is a way that i can display next to each similar post, the tags which match the original queried post’s tags
Thanks for the script, but here is my problem. The tags are ordered in aphlabetical order. In admin dashboard as well as on the page under my posts. The script from Smashing Magazine was getting only the first tag, but since the ordering is in place, I was getting riddiculous results – the displayed related posts were not related at all. Now I have applied your script and getting same results. A solution for me would be, to get say only the first 2 tags. Can you help me out with this, please?
@ all: Sorry for letting you wait for so long without any response on open questions regarding the script. I’m currently facing a lack of time to spend for this stuff, but as soon as I find some I’ll get back to you!
[...] Source : http://www.3mind.at [...]
[...] WordPress : Related posts by tag [EN] [...]
WordPress: Related posts by tags…
…b> Found’ if there aren’t any posts sharing the same tags? I tried to do it myself by adding an else statement, but failed miserably. ……