count number of posts (public , private , protected) by category name

Here is another flexible way to count posts:

Idea:

First I was going to write the SQL query directly, but then I thought it would be more flexible if we could instead just modify the SQL query generated by WP_Query() so it would only return the results count instead of post objects.

Example:

I’ve been playing with these things today and this is what came out of it:

$args = array(
          'post_type'           => 'post',
          'post_status'         => 'publish',
          'category_name'       => 'reykjavik',
       );

$q = new WPSE_121749_Query_Count( $args );
echo $q->count();

where you can change $args to your likings and WPSE_121749_Query_Count is an extension of WP_Query.

Output:

In the above example the output of echo $q->count(); is 95 since
the output of print_r( $q->posts ); is:

Array ( [0] => 95 )

and it doesn’t contain any post objects, since we only want the count.

The Class:

There are many hooks available to modify the WP_Query and I use three filters and one action but there might be better ways to do this using other hooks.

Here is the first version of the class:

/**
 * Class WPSE_121749_Query_Count
 *
 */
class WPSE_121749_Query_Count extends WP_Query 
{       
public function __construct( $args = array() )
{
    add_filter( 'posts_request',    array( $this, 'posts_request'   ) );
    add_filter( 'posts_orderby',    array( $this, 'posts_orderby'   ) );
    add_filter( 'post_limits',      array( $this, 'post_limits'     ) );
    add_action( 'pre_get_posts',    array( $this, 'pre_get_posts'   ) );

    parent::__construct( $args );
}

public function count()
{
    if( isset( $this->posts[0] ) )
        return $this->posts[0];

    return '';          
}

public function posts_request( $request )
{
    remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
    return sprintf( 'SELECT COUNT(*) FROM ( %s ) as t', $request );
}

public function pre_get_posts( $q )
{
    $q->query_vars['fields'] = 'ids';
    remove_action( current_filter(), array( $this, __FUNCTION__ ) );
}

public function post_limits( $limits )
{
    remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
    return '';
}

public function posts_orderby( $orderby )
{
    remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
    return '';
}

}

Leave a Comment