This morning JTk presented me a WordPress riddle:
What I would like to be able to do is ask the MySQL if a category has any posts in it or if it is empty. So I can do one thing if there are posts there and another if that category is empty. And try as I might, no matter how hard I beat my head against it, all I get is a bruised head. And, yes, I have to do this conditional because WP is flawed and will break if I try and do certain things with empty categories…..
Here is the schema ( maybe it helps )
http://blog.kapish.co.in/wp-content/uploads/2008/01/wp_db.pngAnd the worst part of this, is – I know this is trivial so I hate to even ask, but I guess I don’t hate enough not to ask
I asked the “community” and got told that there is not a WP function for this ( um, yeah, thanks…. ) that I shouldn’t make straight db calls ( arrrggg ), and that there are plugins that accomplish similar things…. But no real help, so I decided to ask a ninja….
So we want to get the number of posts per category. JTk, you’re in luck! A quick look at the schema (if that diagram is current) tells me we could query the wp_post2cat table and do a COUNT and a GROUP BY query on the category of interest. Even better, if wp_categories.category_count is what I think it is, that’s a simpler query. But let’s see what the code gives us already. In category.php, there are some tasty sounding functions like get_categories(), get_category(), get_category_by_path(), get_category_by_slug() and so on. I installed a clean version of WordPress, added some categories and assigned some fake posts to them. Then I tried some of these functions to see what’s up.
<?php var_dump(get_categories()); ?>
Output:
array(3) {
[1]=>
object(stdClass)#68 (15) {
["term_id"]=>
&string(1) "3"
["name"]=>
&string(14) "First Category"
["slug"]=>
&string(14) "first-category"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "3"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "4"
["cat_ID"]=>
&string(1) "3"
["category_count"]=>
&string(1) "4"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(14) "First Category"
["category_nicename"]=>
&string(14) "first-category"
["category_parent"]=>
&string(1) "0"
}
[2]=>
object(stdClass)#69 (15) {
["term_id"]=>
&string(1) "4"
["name"]=>
&string(15) "Second Category"
["slug"]=>
&string(15) "second-category"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "4"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "2"
["cat_ID"]=>
&string(1) "4"
["category_count"]=>
&string(1) "2"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(15) "Second Category"
["category_nicename"]=>
&string(15) "second-category"
["category_parent"]=>
&string(1) "0"
}
[3]=>
object(stdClass)#90 (15) {
["term_id"]=>
&string(1) "1"
["name"]=>
&string(13) "Uncategorized"
["slug"]=>
&string(13) "uncategorized"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "1"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "1"
["cat_ID"]=>
&string(1) "1"
["category_count"]=>
&string(1) "1"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(13) "Uncategorized"
["category_nicename"]=>
&string(13) "uncategorized"
["category_parent"]=>
&string(1) "0"
}
}
OK, so it sounds like the person who told JTk there were no built-in WordPress functions for this was lying
This function tells us exactly what we need. A couple of interesting observations, though. I had a category named “Empty Category” with no posts, which does not show up here. The documentation page tells me that I can pass a parameter to include the empty ones easily enough:
<?php var_dump(get_categories(array(‘hide_empty’=>false))); ?>
array(4) {
[0]=>
object(stdClass)#67 (15) {
["term_id"]=>
&string(1) "5"
["name"]=>
&string(14) "Empty Category"
["slug"]=>
&string(14) "empty-category"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "5"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "0"
["cat_ID"]=>
&string(1) "5"
["category_count"]=>
&string(1) "0"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(14) "Empty Category"
["category_nicename"]=>
&string(14) "empty-category"
["category_parent"]=>
&string(1) "0"
}
[1]=>
object(stdClass)#68 (15) {
["term_id"]=>
&string(1) "3"
["name"]=>
&string(14) "First Category"
["slug"]=>
&string(14) "first-category"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "3"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "4"
["cat_ID"]=>
&string(1) "3"
["category_count"]=>
&string(1) "4"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(14) "First Category"
["category_nicename"]=>
&string(14) "first-category"
["category_parent"]=>
&string(1) "0"
}
[2]=>
object(stdClass)#69 (15) {
["term_id"]=>
&string(1) "4"
["name"]=>
&string(15) "Second Category"
["slug"]=>
&string(15) "second-category"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "4"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "2"
["cat_ID"]=>
&string(1) "4"
["category_count"]=>
&string(1) "2"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(15) "Second Category"
["category_nicename"]=>
&string(15) "second-category"
["category_parent"]=>
&string(1) "0"
}
[3]=>
object(stdClass)#90 (15) {
["term_id"]=>
&string(1) "1"
["name"]=>
&string(13) "Uncategorized"
["slug"]=>
&string(13) "uncategorized"
["term_group"]=>
string(1) "0"
["term_taxonomy_id"]=>
string(1) "1"
["taxonomy"]=>
string(8) "category"
["description"]=>
&string(0) ""
["parent"]=>
&string(1) "0"
["count"]=>
&string(1) "1"
["cat_ID"]=>
&string(1) "1"
["category_count"]=>
&string(1) "1"
["category_description"]=>
&string(0) ""
["cat_name"]=>
&string(13) "Uncategorized"
["category_nicename"]=>
&string(13) "uncategorized"
["category_parent"]=>
&string(1) "0"
}
}
Sure enough,there is the empty category. I also noticed that the article count appears in both ->count and ->category_count. I’ll just assume the cached version, ->category_count, will remain correct through the code, but I’m just guessing it doesn’t matter which member we use.
So, that’s fine if we want the whole collection, but what about individual categories? Fortunately, we can extract this same data for both the category ID as well as the name of the category. Here’s an example of each, querying my “First Category” category:
Using ->category_count
<?php var_dump( (int) get_category(’3′)->category_count); ?>
<?php var_dump( (int) get_category_by_slug(‘First Category’)->category_count; ?>
<?php var_dump( (int) get_category_by_slug(‘first-category’)->category_count); ?>
Using ->count
<?php var_dump( (int) get_category(’3′)->count); ?>
<?php var_dump( (int) get_category_by_slug(‘First Category’)->count; ?>
<?php var_dump( (int) get_category_by_slug(‘first-category’)->count); ?>
All of these return the correct result, int(4). Good on ya, WordPress.
Now let’s see how robust the function is. Will it choke on a non-existent category, or return a zero like it should?
<?php var_dump( (int) get_category(’6969′)->category_count); ?>
<?php var_dump( (int) get_category_by_slug(‘This Damn Category’)->category_count); ?>
Both of these do indeed return zero, which is nice and correct.
In practical terms, you can use this code stub to do something will all categories depending on whether or not there are posts:
foreach (get_categories(array('hide_empty'=>false)) as $category){
if ($category->count > 0){
//has posts, do something
}else{
//no posts, do something else
}
}
That’s all there is to it! There’s definitely a built in function to inspect categories, and even some nice examples to go with. Happy WordPress hacking, and don’t forget that now’s the time to upgrade to PHP 5 if you haven’t already



August 13th, 2008 at 1:41 pm
Damn Sam! Ask a Ninja a question, get a ninja answer….
August 13th, 2008 at 2:20 pm
Ureka! It only took me an hour to take your samples and examples and hack it into what I needed.
Hey, we can’t all be ninja’s….
August 14th, 2008 at 9:13 am
That’s a helpful breakdown. I haven’t had to do precisely this, but I figure it’s just a matter of time until I do, so thanks.
September 24th, 2008 at 1:21 am
Heya John,
Thank you for taking the time to write this. I was wondering though: I want to divide all posts from cat ID 4 and all it’s childs in two columns.
I thought of this solution:
x = number of posts in cat 4 en childs.
y = number of posts in first column.
z = number of posts in second column.
If x = even, then divide it in 2 = y = z.
If x is uneven, then add 1, divide that in 2 = y. y – 1 = z.
All I need now is the number of the posts to be able to do this math. When I tried out a few things, I never could get just that number I wanted. I’m not an advanced coder, so I hope I explained it well.
Thx ahead.
September 24th, 2008 at 1:25 am
Ninja John,
Thanks a billion for this – I found a link here via a post of yours in the WordPress forums and tinkered with your array outputs and code snippet to get what I needed.
I wanted to output a list of categories followed by “X posts”, since the formatting of wp_list_categories wasn’t cutting it. Here is what I used:
foreach (get_categories(array(‘hide_empty’=>false)) as $category)
{
echo ‘category_nicename . ‘/”>’ . $category->cat_name . ‘ ‘ . $category->count . ‘ posts’;
}
Obviously one could add tags to style the “X posts” piece differently – in my case I wanted the number of posts to be positioned on the far right.
Thanks again!
September 24th, 2008 at 1:57 am
Hmm, I think I found it:
count); echo $number;?>
Took me a few hours :p
February 1st, 2009 at 6:23 pm
Hay una funcion muy util entre los comentarios de: http://wordpress.org/support/topic/168459
April 25th, 2009 at 2:25 am
Hi John, this worked great for me. Thanks so much. I was wondering though – the way you are able to extract the “count” for categories with either “->category_count” or “->count”, is there an API that lists these functions? I know the ones used are in examples in those documentations, but I couldn’t really find much else.
Regardless, great post!
September 3rd, 2009 at 7:54 am
Hi
Thank you so much for the help: but now I must do it recursively.
I mean: I have to find the number of post in a category+it’s subcategories.
Can you help me?
Actually this is my not recursive code:
$ID_CAT=get_cat_id( single_cat_title(“”,false) );
$POST_NUMBER=(int) get_category($ID_CAT)->category_count;
January 6th, 2010 at 9:32 am
somehow I do not get the point, already tried everything, but will not work
January 21st, 2010 at 9:02 pm
[...] post on Getting the number of posts per category showed me how to do [...]
April 14th, 2010 at 12:29 am
Thanks John, these info helped me a lot.
April 27th, 2010 at 2:05 am
Thank you John for these tips.Just what I needed!
July 14th, 2010 at 12:12 am
[...] ขอขอบคุณบทความ : http://jhherren.wordpress.com/2008/08/13/getting-the-number-of-posts-per-category-in-wordpress [...]
July 14th, 2010 at 12:14 am
[...] ขอขอบคุณบทความ : http://jhherren.wordpress.com/2008/08/13/getting-the-number-of-posts-per-category-in-wordpress [...]
July 14th, 2010 at 12:15 am
[...] ขอขอบคุณบทความ : http://jhherren.wordpress.com/2008/08/13/getting-the-number-of-posts-per-category-in-wordpress [...]
August 29th, 2010 at 6:10 am
very useful. just what I needed and number 1 on google for my query of “get num posts in category”
thanks for sharing.
October 8th, 2010 at 10:12 pm
I’d like to display the number of posts for one specific gallery and I’m not sure how to get there from the code you provided. Help?
December 21st, 2010 at 9:20 am
I was very annoyed of this problem too and tried hours to fix it with my poor PHP knowledge, but i found the answer with backspace. I think this is also ^what you are looking for:
$porsas = get_category(’27′)->count;
echo $porsas
February 17th, 2011 at 2:32 am
Hi, I used the following codes to list all the categories that I have on my site, but the issue is that I have too many categories (100+). So, I would like to paginate the category listing. (i.e 10 categories each page… etc) I don’t know how I would approach this using the get_categories function within WordPress. Help??? Thanks!
‘name’,
‘order’ => ‘ASC’
);
$categories=get_categories($args);
foreach($categories as $category) {
echo ‘Category: term_id ) . ‘” title=”‘ . sprintf( __( “View all posts in %s” ), $category->name ) . ‘” ‘ . ‘>’ . $category->name.’ ‘;
echo ‘ Description:’. $category->description . ”;
echo ‘ Post Count: ‘. $category->count . ”; }
?>
March 3rd, 2011 at 1:43 am
thanks so much ! i am finding this !…
March 14th, 2011 at 8:31 am
thanks for the post !
i think WordPress has count _ author _ post so it’s will be nicer if WP has count post in a specific category !@
April 15th, 2011 at 8:44 am
Thanks for the post, give me the know about category templating. Currently each category shows 10 post I know I can change this via admin panel. Is there any where in the code I can add how many post it should display on the page?
Cheers,
Shovan S
Web Designer / Creative Director
t: http://www.twitter.com/ShovanSargunam
f: http://www.facebook.com/ShovanSargunam
w: http://www.shovan.org / http://www.thescube.com
y: http://www.youtube.com/ShovanSurya
l: http://www.linkedin.com/in/ShovanSargunam
f: http://www.flickr.com/photos/shovan