Hi guys,
Does anyone know how to do this? I would like to display the number of posts that are assigned under each tag on my blog. Like:
Dog (8)
Cat (3)
Fish (15)
and so on...
Hi guys,
Does anyone know how to do this? I would like to display the number of posts that are assigned under each tag on my blog. Like:
Dog (8)
Cat (3)
Fish (15)
and so on...
At least can someone please tell me if this is possible or not. I have been stuck on this thing for the past week now and would prefer to know so I can move on.
Thanks.
Sure i'll bite.
<?php
// Select all the post tag IDs
$the_tags = $wpdb->get_col("SELECT term_id
FROM $wpdb->term_taxonomy WHERE taxonomy = 'post_tag'" );
// Loop over each ID, and grab associated data
foreach($the_tags as $tag_id) {
// Get information on the post tag
$post_tag = get_term( $tag_id, 'post_tag' );
// Print the tag name and count (how many posts have this tag)
echo $post_tag->name.' ( '.$post_tag->count.' )<br />';
// Unset the data when it's not needed
unset($post_tag);
}
?>
Shame wp_tag_cloud doesn't provide the tag count, else this would have been a little easier.
The above is a working solution though.... A list of post tags and how many posts have that tag...
It can be modified for other uses... and there may be an easier way, but noone else offered anything else up, so i hope that helps... ;)
Thank you so much for biting t31os_!!!
There's a little problem though, currently I list my tags alphabetically:
I have a A-Z navigation at the top of the page and 25 blocks of code as below:
<div id="a" class="abc_tags">
<ul>
<?php
$tags = get_tags( array('name__like' => "a", 'order' => 'ASC') );
foreach ( (array) $tags as $tag ) {
echo '<li><a href="' . get_tag_link( $tag->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $tag->name ) . '" ' . '>' . $tag->name.'</a></li>';
}
?>
</ul>
</div>
Clicking on "A" in the navigation for example brings the person down the page to A tags and clicking K brings them further down the page to the K tags (anchor links). So that's why I need the code to be inside their own blocks (loops?) like above.
I tried mixing your code to integrate with mine but after about a thousand fatal errors I turn to you again for help (I'll learn PHP very soon I promise).
You code produces a vertical tag cloud that is in no particular order.
I need it to be in alphabetical order and also for each alphabet tag to be inside it's own loop/div (I will then reproduce it 26 times for each alphabet).
Ok well that's a bit more of a challenge. You left out these crucial details in your first post.
However...
This works..
<?php
$query_string = '
SELECT *,name FROM '.$wpdb->prefix.'term_taxonomy
JOIN '.$wpdb->prefix.'terms
ON '.$wpdb->prefix.'term_taxonomy.term_id = '.$wpdb->prefix.'terms.term_id
WHERE '.$wpdb->prefix.'term_taxonomy.taxonomy = "post_tag"
ORDER by '.$wpdb->prefix.'terms.name ASC
';
$post_tags = $wpdb->get_results($query_string);
?>
<div id="a" class="abc_tags">
<ul>
<?php
foreach($post_tags as $key => $tag) {
$newletter = substr($tag->name, 0, 1);
if($newletter !== $letter && $key != 0) { ?>
</ul>
</div>
<div id="<?php echo strtolower($newletter); ?>" class="abc_tags">
<ul>
<?php } $letter = substr($tag->name, 0, 1); ?>
<li><a href="<?php echo get_tag_link($tag->term_id); ?>" title="<?php echo sprintf( __( "View all posts in %s" ), $tag->name ); ?>"><?php echo $tag->name.' ('.$tag->count.')';?></a></li>
<?php
}
?>
</ul>
</div>Thank you so much t31os_!!!
It works perfectly and greatly reduced my original code size. As a token of my appreciation I want to give you two free premium wordpress themes and a premium plugin. Email me if you're interested (fiatlvx@hotmail.com),
Thanks again.
No problem, you're welcome...
And thanks, i'll be happy to grab a copy of whatever you'd like to share mate, i'll drop you an email shortly..
Hy guys,
this is very useful, but to display the number of posts under one tag?
thanks
Very useful, thanks guys!
The code suggested by t31os_ works perfectly.
I was wondering if there's a straightforward way to display post titles in a comma separated list, rather than the tag count? And for each post title to link to its respective post. So it's a combination of t31os_'s solution and the solution posted here:
http://wordpress.org/support/topic/328118?replies=8
For example, say I've published the following three posts:
Post title: Old Yeller is a dog
Tagged: DogPost title: Old Yeller likes steak
Tags: Dog, FoodPost title: Garfield will eat anything
Tags: Cat, Food
This is the list I want to create:
Any ideas are very much appreciated!
@markellison
You'd essentially be grabbing any post with a tag then right? As you're grabbing all tags.
This might work out as quite an intensive query for a site with lots of tags and lots of posts, but it will do the job.
$tags_and_posts = $wpdb->get_results("
SELECT tr.object_id,p.post_title,p.guid,t.name
FROM wp_term_relationships tr
JOIN wp_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
JOIN wp_posts p ON tr.object_id = p.ID
JOIN wp_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'post_tag'
AND p.post_status = 'publish'
AND p.post_type = 'post'
");
$tag_array = array();
foreach( $tags_and_posts as $unwanted_key => $result ) {
$tag_array[$result->name][] = '<a href="'. $result->guid .'">' . $result->post_title . '</a>';
//$tag_array[$result->name][] = '<a href="'. get_permalink( $result->object_id ) .'">' . $result->post_title . '</a>';
}
print '<ul>';
foreach( $tag_array as $tag => $post_titles ) {
print '<li>' . $tag . ' ( ' . implode( ', ', $post_titles ) . ' )</li>';
}
print '</ul>';
I've left a piece of commented code in there to, that will fetch the permalink for each result, but it would work out to be a more intensive query, the guid method is reliable(should be) and avoids the extra lookup, but use whichever suits you (comment/uncomment as required).
@GiuseppeM
this is very useful, but to display the number of posts under one tag?
Something simple like this should work..
$the_term = get_term_by( 'name', 'your-tag-name-here', 'post_tag' );
echo $the_term->count;@t31os_
Thanks so much! I will try this the first chance I get.
Maybe you could help with a related issue. I would like to use tags that include a comma, the reason being is I'm tagging by peoples' names in the format, "Lastname, Firstname". But whenever I try to make tags like "Johnson, Jack" "Kay, Peter" Smith, Alex", WP splits them in to distinct tags: Alex, Jack, Johnson, Kay, Peter, Smith.
I have tried a few plugins (Simple Tags, Page Tagger) with no luck.
Any ideas are very much appreciated!
This reminds me of a Trac ticket i read regarding terms with commas.
http://core.trac.wordpress.org/ticket/13606
However, i have discovered something that does work for introducing commas into post tags.
Lastname& #44; Firstname
&# 44;..being a comma... :)
Without the space between the hash and the fours (not sure if forum will convert them).
@t31os_
I tried your suggestion about displaying post titles (with permalinks) alongside tags, but I can't really get it to work. You are correct that I am trying to grab any post with a tag. I want to create a list of all my tags and, in a list beneath each tag, place permalinks/titles of all posts that are tagged with that tag. Additionally, the tag list should be listed in alphabetical order and grouped by letter. That's a mouthful! But essentially it's a combination of this solution:
<?php
$query_string = '
SELECT *,name FROM '.$wpdb->prefix.'term_taxonomy
JOIN '.$wpdb->prefix.'terms
ON '.$wpdb->prefix.'term_taxonomy.term_id = '.$wpdb->prefix.'terms.term_id
WHERE '.$wpdb->prefix.'term_taxonomy.taxonomy = "post_tag"
ORDER by '.$wpdb->prefix.'terms.name ASC
';
$post_tags = $wpdb->get_results($query_string);
?>
<div id="a" class="abc_tags">
<ul>
<?php
foreach($post_tags as $key => $tag) {
$newletter = substr($tag->name, 0, 1);
if($newletter !== $letter && $key != 0) { ?>
</ul>
</div>
<div id="<?php echo strtolower($newletter); ?>" class="abc_tags">
<ul>
<?php } $letter = substr($tag->name, 0, 1); ?>
<li><a href="<?php echo get_tag_link($tag->term_id); ?>" title="<?php echo sprintf( __( "View all posts in %s" ), $tag->name ); ?>"><?php echo $tag->name.' ('.$tag->count.')';?></a></li>
<?php
}
?>
</ul>
</div>
and what you proposed here:
$tags_and_posts = $wpdb->get_results("
SELECT tr.object_id,p.post_title,p.guid,t.name
FROM wp_term_relationships tr
JOIN wp_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
JOIN wp_posts p ON tr.object_id = p.ID
JOIN wp_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'post_tag'
AND p.post_status = 'publish'
AND p.post_type = 'post'
");
$tag_array = array();
foreach( $tags_and_posts as $unwanted_key => $result ) {
$tag_array[$result->name][] = '<a href="'. $result->guid .'">' . $result->post_title . '</a>';
//$tag_array[$result->name][] = '<a href="'. get_permalink( $result->object_id ) .'">' . $result->post_title . '</a>';
}
print '<ul>';
foreach( $tag_array as $tag => $post_titles ) {
print '<li>' . $tag . ' ( ' . implode( ', ', $post_titles ) . ' )</li>';
}
print '</ul>';
Can you help? Major high fives if so!
Also, if it makes a difference, I am actually tagging WP pages, not posts, by using the Simple Tags plugin.
Try something like this...
$tags_and_posts = $wpdb->get_results("
SELECT tr.object_id,p.post_title,p.guid,t.name
FROM wp_term_relationships tr
JOIN wp_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
JOIN wp_posts p ON tr.object_id = p.ID
JOIN wp_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'post_tag'
AND p.post_status = 'publish'
AND p.post_type = 'post'
ORDER by t.name
");
$tag_array = array();
$letters = array();
foreach( $tags_and_posts as $unwanted_key => $result ) {
$tag_array[$result->name][] = '<a href="'. $result->guid .'">' . $result->post_title . '</a>';
//$tag_array[$result->name][] = '<a href="'. get_permalink( $result->object_id ) .'">' . $result->post_title . '</a>';
}
foreach( $tag_array as $tag => $post_titles ) {
$letter = $tag{0};
$letters[ $letter ][] = $tag . ' ( ' . implode( ', ', $post_titles ) . ' )';
}
foreach( $letters as $tag_letter => $tags ) {
// Create a list for each letter
print '<ul><li>' . implode( '</li><li>', $tags ) . '</li></ul>';
}
If you don't need a list per letter you can simply add this to the query as i've done in the above.
ORDER by t.name
Hope that helps... :)
Thanks man. I just tried that but I get no content displayed on my page at all. Do I need to use any other code, other than what you've given in your most recent comment?
Make sure it's inside the necessary PHP tags...
<?php
// THE CODE
?>Yeah, got those :) Something is still wrong though...
Ah ha! It's the fact that I'm tagging WP pages and not posts. When I tag a post, your code works perfectly! Exactly as I would have liked. But the code is not picking up tagged WP pages (made possible by the Simple Tags plugin).
I'm going to play around some more...
Got it! Just changed
AND p.post_type = 'post'
to
AND p.post_type = 'page'
...and it worked like a charm. Case close. t31os_ can I buy you a beer?
Appreciate the offer, unfortunately i don't have a "Buy me a beer" facility ..
Glad to hear it's all working for you though... :)
Hi t310s_,
I have a new challenge... :)
The client now wants the list to be alphabetized not by first word in the tag names, but rather by the second word of the tag names. The reason is that the tags are actually author names and the list I'm creating is meant to be an index.
You can see what I have so far here: http://bit.ly/aK3oRH
Here is the code I'm using (a slight modification of your code to account for my db table names; and I made the html print out in a table rather than ul/li)
<?php
$tags_and_posts = $wpdb->get_results("
SELECT tr.object_id,p.post_title,p.guid,t.name
FROM wp_dub_term_relationships tr
JOIN wp_dub_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
JOIN wp_dub_posts p ON tr.object_id = p.ID
JOIN wp_dub_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'post_tag'
AND p.post_status = 'publish'
AND p.post_type = 'page'
ORDER by t.name
");
$tag_array = array();
$letters = array();
foreach( $tags_and_posts as $unwanted_key => $result ) {
$tag_array[$result->name][] = '<a href="'. get_permalink( $result->object_id ) .'">' . $result->post_title . '</a>';
}
foreach( $tag_array as $tag => $post_titles ) {
$letter = $tag{0};
$letters[ $letter ][] = $tag . ' <td class="issue-numbers"> ' . implode( ' <span class="sep">/</span>', $post_titles ) . ' </td> ';
}
foreach( $letters as $tag_letter => $tags ) {
// Create a list for each letter
print '<table id="index-table"><tr><td class="author-name">' . implode( '</td></tr><tr><td class="author-name">', $tags ) . '</td></tr></table>';
}
?>
If there is a way to achieve this programatically, it would be absolutely huge! If you can solve this, I honestly want to buy you a beer. :)
All best,
Mark
Actually, this is going to be harder than I thought. Some people's names are like: Ann Marie Hourihane (alphabetized by H)
So is it possible to alphabetize the list by the last word in a tag name, regardless of how many words make up the tag name?
Assuming there always be a space between the names you could split the string by the spaces to work out the last word.
Something like replacing..
// Ignore this line
$letter = $tag{0};
..with..
// Ignore this line
$letter = ( strpos( $tag, ' ' ) ) ? explode( ' ',$tag ) : $tag;
if( is_array( $letter ) ) {
$letter = array_reverse( $letter );
$letter = $letter[0]{0};
}
else {
$letter = $letter{0};
}
The commented line just works around a forum bug which removes tabbing on the first line.
Hi again, thanks so much for the quick reply. Your suggested code worked wonders! The names are now grouped by the last word. Check it out: http://bit.ly/aK3oRH
Two issues still need to be solved, though.
1) "letter groups" should be printed in alphabetical order. So this list:
Antonin Artaud 1
Benedict Anderson 10
Fergus Allen 13 /27
Should be printed before this list:
Angela Bourke 4 /21
Greg Baxter 15 /27 /29 /30 /32 /34
Harry Browne 6 /8 /10 /21 /25 /33
2) within each "letter group", the names should be in alphabetical order. So this list:
Antonin Artaud 1
Benedict Anderson 10
Fergus Allen 13 /27
Should actually print like this:
Fergus Allen 13 /27
Benedict Anderson 10
Antonin Artaud 1
...because Allen comes before Anderson which comes before Artaud.
Ok needs further modification then..
Change.
// Ignore
$letter = $tag{0};
$letters[ $letter ][] = $tag . ' <td class="issue-numbers"> ' . implode( ' <span class="sep">/</span>', $post_titles ) . ' </td> ';
To.
// Ignore
$letter = ( strpos( $tag, ' ' ) ) ? explode( ' ',$tag ) : $tag;
if( is_array( $letter ) ) {
$letter = array_reverse( $letter );
$surname = strtolower( $letter[0] );
$letter = $letter[0]{0};
}
else {
$surname = strtolower( $letter );
$letter = $letter{0};
}
$letters[ $letter ][ $surname ] = $tag . ' <td class="issue-numbers"> ' . implode( ' <span class="sep">/</span>', $post_titles ) . ' </td> ';
Also add the following...
// Ignore
ksort( $tags );
After.
foreach( $letters as $tag_letter => $tags ) {
Think that should do it... let me know.. ;)
I think we're almost there. Now the "letter groups" are in alphabetical order by surname, which is great. But the groups themselves are jumbled up.. it starts with "F", then "D", then "O", etc. Have a look: http://bit.ly/aK3oRH
Here is the full code snippet FYI
<?php
$tags_and_posts = $wpdb->get_results("
SELECT tr.object_id,p.post_title,p.guid,t.name
FROM wp_dub_term_relationships tr
JOIN wp_dub_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
JOIN wp_dub_posts p ON tr.object_id = p.ID
JOIN wp_dub_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'post_tag'
AND p.post_status = 'publish'
AND p.post_type = 'page'
ORDER by t.name
");
$tag_array = array();
$letters = array();
foreach( $tags_and_posts as $unwanted_key => $result ) {
$tag_array[$result->name][] = '<a href="'. get_permalink( $result->object_id ) .'">' . $result->post_title . '</a>';
}
foreach( $tag_array as $tag => $post_titles ) {
// Ignore
$letter = ( strpos( $tag, ' ' ) ) ? explode( ' ',$tag ) : $tag;
if( is_array( $letter ) ) {
$letter = array_reverse( $letter );
$surname = strtolower( $letter[0] );
$letter = $letter[0]{0};
}
else {
$surname = strtolower( $letter );
$letter = $letter{0};
}
$letters[ $letter ][ $surname ] = $tag . ' <td class="issue-numbers"> ' . implode( ' <span class="sep">/</span>', $post_titles ) . ' </td> ';
}
foreach( $letters as $tag_letter => $tags ) {
// Ignore
ksort( $tags );
// Create a list for each letter
print '<table id="index-table"><tr><td class="author-name">' . implode( '</td></tr><tr><td class="author-name">', $tags ) . '</td></tr></table>';
}
?>Before this line..
foreach( $letters as $tag_letter => $tags ) {
Add.
ksort( $letters );SCORE! IT WORKS!
I cannot thank you enough!!!!
You're welcome.. ;)
NOTE: You don't need those // Ignore lines in the code, they were intended to be ignored (works around a forum bug when posting code).
Hello, me again!
I've restructured my content and needed to try a little tweak. For the links to the relevant posts, I needed to display the post excerpts rather than the post titles. I changed the code to the following and it worked like a charm :)
'post_title' to 'post_excerpt'
and
'post-titles' to 'post_excerpts'
I'm going to mark the topic resolved as it appears you have things working as required.
Any problems, feel free to start a new thread. :)
This topic has been closed to new replies.