Counting Posts In WordPress

Every now and then you would need to display the total post count in your WordPress application (website). There are several methods you can use for such a simple task, but can you tell the difference and choose the right method (function) which runs faster and consumes less resources? I’d like to share my findings with you in this post.

1. Get total post count

Since version 2.5.0, WordPress came with a built-in function called wp_count_posts, which can be used to “count number of posts of a post type and if user has permissions to view.” So there are 2 parameters for this function: $type and $perm.

$type can be available post types in your WordPress, like “post”, “page” or any custom post type. $perm takes an empty string by default, you can change it to “readable“, so if the user is logged in, it only counts posts are readable by the user.

wp_count_posts() will return an object with the post statuses as the properties, you need to use syntax like this to retrieve the count of published posts:

$count = wp_count_posts(); 
$publish_post_count = $count->publish;

It will be a little bit tricky if you want to get the count of private posts. By default, if the user isn’t logged in, wp_count_posts() won’t include “private” status into its properties.

In the function description, the developer told us there’s another method to count posts which “is to count the amount of items in get_posts(), but that method has a lot of overhead with doing so.” Now we know wp_count_posts() runs with better performance but with it, we can only specify the post type of posts, we must find other solutions if we need to count posts in certain category or tag, or even count posts from a complex query.

2. Count posts in a category or tag

You might not think of it right away, but you must see it many times. Yes, I’m talking about the “Count” field in your Categories admin panel. Here’s a screenshot of mine:

Categories admin panel

WordPress stores the count number of posts of a category (term) in the database, in the count column of $wpdb->_term_taxonomy table exactly. So if we can access a term object in WordPress, we can get the count number of posts in that term. For example:

$term = get_term( 1, 'category' ); 
$count = $term->count;

3. Count posts from a not-so-simple query

WordPress is very powerful and the power comes from tons of built-in classes and functions, among them I love WP_Query most. It gets evolved almost every time WordPress gets upgraded. Now we can use meta_query, tax_query and date_query to accomplish complex post queries.

In such scenario, say if we’d like to know how many posts have the meta key / value pair “foo = bar”, no doubt we would use WP_Query to query posts we need. Let’s see how can we query posts and get total post count at the same time:

As you can see, the found_posts property does the trick. We can get total post count without query them all (by setting posts_per_page t0 -1).

If you’ve read some articles about optimizing WordPress queries, and developed a good habit to set “no_found_rows” to true when you don’t need pagination in your WP_Query, please note this is not the case. If we set “no_found_rows” to true, the found_posts property will be set to 0, and this method won’t be available for you.

4. What about counting items in get_posts()?

If you must use get_posts() to query posts and count the results array with PHP function count to get the total post count, I’ll say please must set these 2 arguments: "cache_results => false" and "fields => ids".

They can help you to use minimum resources when getting posts with the greedy monster “posts_per_page = -1“.

5. Get total post count with WP REST API

WP REST API returns the total post count in the response headers. Here’s a snippet from my AngularJS WordPress Theme:

In line 8, I pass the headers to the success callback function so I can get the response headers returned by WP REST API. In line 13 I use console.log to display the value I want, which is “X-WP-Total“. If we trace back to the source code of WP REST API, we can see that the “X-WP-Total” is exactly the found_posts property from WP_Query.

6. Install Query Monitor on every WordPress application you develop

It’s impossible that a professional WordPress developer can do her / his job right without Query Monitor. I used to disable the admin bar on the front end but now I enable it on every WordPress application I develop. Why? Because I need to check the performance overview from Query Monitor displayed at the admin bar.

After activating the Query Monitor you should be aware if there’s a db.php in your wp-content directory. If you can’t see the file or it’s not a symlinked file, Query Monitor can still work but you can’t see some extended information. To fix this, you can follow the instruction on the wiki page of this plugin.


I hope you enjoy these findings as much as I do. Please feel free to let me know your thoughts or share some tips with me. I’ll be back in April with new AngularJS WordPress theme tutorials. See you then!

24 responses

  1. Hi Yoren,

    Great article! Hopefully you can help with something. I am looking to simply display the total number of posts using the WP-API, but I am unsure of how X-WP-Total works. Would you be able to give any tips on adding the Total Number of posts to the top of a list? I need to use the WP-API for an app.

    Cheers

    Damien

    1. Yoren Chang Avatar
      Yoren Chang

      Hey Damien,

      I assumed you used the wp_remote_get to call the WP API, so it would be like:


      $url = home_url( 'wp-json/wp/v2/posts' );
      $r = wp_remote_get( $url );
      echo 'Total posts: ' . $r['headers']['x-wp-total']);

  2. Hi Yoren,

    Thank you for your post. I am not very savvy in PHP and can manipulate some basic WP functions.

    Would you be able to help with the following: I have an index page with posts where I use a widget (side bar) to display categories. I managed to echo total post count for the Category “All”. But I struggle to count posts for each category. The code I use for the Category nav bar is this one:

    ‘name’,
    ‘parent’ => 0
    );
    $categories = get_categories($args);
    ?>

    All (publish;
    echo $total; ?>)

    ‘name’,
    ‘parent’ => $category->term_id
    );
    $child_categories = get_categories($args_child);
    if( count( $child_categories ) ){
    echo

    term_id ) . ‘” title=”‘ . sprintf( __( “View all posts in %s” ), $category->name ) . ‘” ‘ . ‘>
    ‘ . $category->name.’

    ‘;
    ?>

    <?php
    foreach($child_categories as $child_category) {
    echo 'term_id ) . ‘” title=”‘ . sprintf( __( “View all posts in %s” ), $child_category->name ) . ‘” ‘ . ‘>’ . $child_category->name.’ ‘;
    }
    ?>

    <?php
    echo ' ‘;
    }
    else{
    echo ‘
    term_id ) . ‘” title=”‘ . sprintf( __( “View all posts in %s” ), $category->name ) . ‘” ‘ . ‘>’ . $category->name.’

    ‘;
    }
    ?>

    Could you please help me count and display category posts? E.g. “Best practice (17)”

    Many thanks,
    Anton

    1. Yoren Chang Avatar
      Yoren Chang

      Hi Anton, if the term object is “$child_category” or “$category”, you can get the total post count of it by accessing $child_category->count. That should work.

  3. Hello dear.
    i have a question.
    i want to get the post count of all the categories. (u explain how to do this, but i don’t know where is the right place to add the codes). i want the total number of post count in “/wp-json/posts/types”.
    (for q 1, i use this: wp-json/posts/types/posts/taxonomies/category/terms and then sum all the count – i know it’s not good but for now, it is my only way).

    1. Yoren Chang Avatar
      Yoren Chang

      Hi Nick, if not creating a custom endpoint for such purpose, I actually think your solution is the best we can do.

  4. Hi Yoren, do you know how to get the comment counts and added the response in wp-api v2 scheme?

    1. Yoren Chang Avatar
      Yoren Chang

      Hi, Jon,

      When you access the route for the comments of a certain post like: http://demo.wp-api.org/wp-json/wp/v2/comments?post=1, you can get the comments from the response headers (with the key “X-WP-Total”).

      1. Thanks for your response.

        I’m looking something to extend the JSON response and add the comment count per post when calling this url /wp-json/wp/v2/posts

        1. Yoren Chang Avatar
          Yoren Chang

          Hey so this post should help you with it: https://1fix.io/blog/2015/06/26/adding-fields-wp-rest-api/.

        2. Yep that post is really helpful! Thank you 🙂

  5. Hi,
    thanks a lot for the article.
    I am trying to use it to create a shortcode here I specify the category or I want to show the count of posts it has, and the function returns the number, so i dont have to add function for every category.

    I tried to use your method #2, but i end up either in a broken function (white page) or nothing at all get displayed.

    can you please help me by understanding what do i need to wrap the code with, so it works?
    also, any input in how to turn it to a shortcode that i can control from the post creation pages will be much appreciated.
    thanks a lot

    1. Yoren Chang Avatar
      Yoren Chang

      Hey Atef, without viewing your code I can’t figure out what’s wrong exactly. Feel free to send me a copy of your code to yoren[at]1fix.io.

      1. Hi Yoren,
        Thank you very much.
        I have sent you an email. Please check at your convenience.

        thanks again

        1. Yoren Chang Avatar
          Yoren Chang

          Got it and just replied!

  6. So I notice that the counts for the terms are for parent posts and child posts. Is there a way to get the totals for parent posts only of a taxonomy term (no child relationship on terms)

  7. Hi,
    thanks for the article, that is my question, is it possible to count all post views of a specific author?

    something like:

    authorname has 12 posts
    total view of 12 posts: 100 views

    thank you again

  8. Murtaza Avatar
    Murtaza

    Hello Dear Yoren Chang,
    Thank you very much to share knowledge with us I am new to REST API.
    I Understand how to get posts from another website using API I want to add Number Pagination under my post list so I can load Next Page with different posts http://prntscr.com/fxrf6n See example.
    Can you guide me how ?

    Thank you

  9. Yoren Chang Avatar
    Yoren Chang

    Hey Murtaza,

    Thanks for reaching out. But adding pagination with WP API is a much advanced topic so I don’t have a simple and free solution for it.

    Best,
    Yoren

  10. Hi Yoren,
    Great article! I’m trying to create a shortcode that will display the category count of a custom post type. I have a custom post type called testimonials and have a handful of categories. I’d like the shortcode to display the count of a particular category. Here is my code but it’s not working for me. Trying to adapt a few things from your article but needing some help. Any thoughts would be appreciated.

    Thanks in advance!

    function review_category_post_count( $atts ) {

    $atts = shortcode_atts( array(
    ‘category’ => null,
    ‘type’ => null
    ), $atts );

    $term = get_term_by( ‘slug’, $atts[‘category’], ‘category’);
    $tpt = $atts[‘type’];

    if( get_post_type() == $tpt ) {
    return $term->count;
    }

    }
    add_shortcode( ‘category_post_count’, ‘review_category_post_count’ );

    1. Yoren Chang Avatar
      Yoren Chang

      Hi Brian,

      I don’t know the context of your code so can’t be sure about it. Where would you put this shortcode and can you get the $term correctly?

      1. Hi Yoren,
        I’m adding the shortcode to a page so that I can display the post count for a particular category within the testimonials post type. No I wasn’t able to get the term correctly.

        Thanks

        1. Yoren Chang Avatar
          Yoren Chang

          If that’s the case your code won’t work because `get_post_type()` will always be “page” I think?

          1. Hi Yoren,
            Ok I’ll look into that – do you have any suggestions / different code.

            Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *