10

I see that it is possible to sort a user query by the number of posts each user has, but is it possible to exclude users with zero posts from the result? In the Wp_User_Query class there is a pre_user_query action, but query strings are a huge weak point, so I'm not sure what sort of filter action I'd want to use here.

7
  • Would it be any less taxing to simply discard from the results, those users who's post_count == 0?
    – GhostToast
    Commented Dec 19, 2012 at 17:41
  • 3
    I was just getting ready to close this as a totally moronic question. WordPress does this automatically with the get_posts_by_author_sql function that generates the SQL for the get_authors() query. Users must have a published or private post to be included in the results. #facepalm Commented Dec 19, 2012 at 17:58
  • cool glad you found the answer
    – GhostToast
    Commented Dec 19, 2012 at 17:58
  • Me too! Though there is no option to close the question for the reason of stupidity. Thanks for chiming in though. I will apply your counsel because I want to save the get_authors() result as a transient... then I can simply skip the current author without needing to do a query every time. Commented Dec 19, 2012 at 18:00
  • 1
    This questions isn't stupid, it got upvotes, please provide your solution as an answer as it can help others.
    – Wyck
    Commented Dec 19, 2012 at 18:08

3 Answers 3

10

Well I have come up with 2 solutions.

Solution 1 - foreach loop and verify each user

This one is based off of @GhostToast's solution, but with updated WordPress functions

//new query with default args
$author_query = new WP_User_Query();

// Get the results
$authors = $author_query->get_results();

if( $authors ) {

    foreach( $authors as $author ) {

     if ( count_user_posts( $author->id ) >= 1 ) {

        echo $author->display_name . '</br>';
    }
}
} else { 
    echo "no users found"; 
}

Solution 2 - fancy pants pre_user_query action

This is what I was thinking of when I posted my question once I found the pre_user_query action in the WP_User_Query class. If you pass in post_count as your orderby parameter then some fancy SQL querying that I never would've figured out on my own happens to join the proper tables together. So what I did was copy that join statement and add it on to my own. This would be better if I could check for its presence first before adding it... perhaps I will use a string match in the future. But for now since I am the one setting up the query I know it isn't there and I just won't worry about it yet. So the code turned out like so:

function authors_with_posts( $query ) {

    if ( isset( $query->query_vars['query_id'] ) && 'authors_with_posts' == $query->query_vars['query_id'] ) {  
        $query->query_from = $query->query_from . ' LEFT OUTER JOIN (
                SELECT post_author, COUNT(*) as post_count
                FROM wp_posts
                WHERE post_type = "post" AND (post_status = "publish" OR post_status = "private")
                GROUP BY post_author
            ) p ON (wp_users.ID = p.post_author)';
        $query->query_where = $query->query_where . ' AND post_count  > 0 ';  
    } 
}
add_action('pre_user_query','authors_with_posts');

and then to use it

$args = ( array( 'query_id' => 'authors_with_posts' ) );  
$author_query = new WP_User_Query( $args );

The idea for a query_id parameter is from An Introduction to WP_User_Class

Which is also just a very good reference on WP_User_Query

3
  • 1
    This is lovely. Now all we need is a way to adjust the pagination page count to the new reworked list...
    – Christine Cooper
    Commented Aug 31, 2014 at 17:37
  • Good call. Don't know how to do that. Commented Sep 1, 2014 at 21:03
  • author->id is now author->ID (small change but id is depreciated)
    – ejntaylor
    Commented Jan 26, 2018 at 10:19
4

Since 4.4, you can simply use the `has_published_posts' parameter.

Example:

$authors = get_transient('mytheme_all_authors');
if (empty($authors)){

    $user_args = array(
    'role__in'    => array('Author', 'Administrator', 'Contributor'),
    'orderby' => 'post_count',
    'order'   => 'DESC',
    'count_total'  => true,
    'has_published_posts' => array('post'),
    );

    $authors = new WP_User_Query( $user_args );
    set_transient('mytheme_all_authors', $authors, 1 * HOUR_IN_SECONDS );
}

$total= $authors->get_total();
$authors = $authors->results;
foreach ( $authors as $user) {
    // loop through your users....

has_published_postscan be either true/false (or null), or an array of post types (like in this example).

Note: I'm using transients here because this specific query can get pretty heavy depending on the system so it makes sense to store it for future uses.

0

Submitting as answer for closure:

   $all_members = get_users();
      foreach($all_members as $member){
        $post_count = count_user_posts($member->ID);
        if(empty($post_count)) {
            $bad_writers[] = $member->ID;
            continue;
        } else {
            // do something;
        }
    }
6
  • Is that the workaround required to get users of all roles? I'm finding that leaving that argument blank is not returning all the users in multisite. Commented Dec 19, 2012 at 18:40
  • get_users_with_role() is not a WordPress function or have I been looking at my computer too long? Commented Dec 19, 2012 at 18:42
  • 1
    It does not exists. Searching 966 files for "get_users_with_role": 0 matches across 0 files. Also get_usernumposts is depreciated, use count_user_posts()
    – Wyck
    Commented Dec 19, 2012 at 18:53
  • argh! my apologies. this was a function i wrote for a members based site. you can just use get_users() and pass whatever parameters you want to it: codex.wordpress.org/Function_Reference/get_users
    – GhostToast
    Commented Dec 19, 2012 at 20:15
  • @GhostToast Please just update your answer.
    – kaiser
    Commented Dec 20, 2012 at 8:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.