I want to display Y number of authors’ info randomly. These authors have to have at least X numbers of posts published.

Please keep in mind that this would be for a blog with thousands of users where most of them have published 0 posts.

I have looked at functions like wp_list_authors() and WP_User_Query() but I cant seem to be able to set the minimum number of posts each author needs to have.

I have tried to get the authors with those functions and then, with a loop, test for each author id and see if they have posted X number of posts or more. (I want to avoid this because it seems too tedious and might be too poor performance wise.

I could order them in descending order, shuffle the array and display the users’ info, but I do not want this because I prefer to showcase users with low number of posts.

If I order them in ascending order, I would get hundrends or thousands of users with 0 posts. However, here I can use wp_list_authors() as indicated by @s_ha_dum in: Total number of authors with more than one post that excludes authors with 0 posts but what if I want to get users that have at least 2 or more posts?

Finally, I could use a pre_user_query filter as explained by @helgatheviking in: WP_User_Query to exclude users with no posts

Is this the best solution?What about performance? Is there a better solution? If so, what would you recommend me do?

2 Answers
2

You can get rid of most of your code above. WP_User_Query has an include parameter (introduced in WordPress 3.9)

include (array) – List of users to be included.

So we need to get a random array of author ID’s. I have modified your count_users_with_posts() a bit here to extend it to make it more dynamic and to get a set amount of authors randomly. I also had to repair a few bugs (some SQL errors, specially this line: WHERE post_count > %s ORDER BY count DESC. You should enable debugging when developing 🙂)

CAVEAT: This works on my local install with 4 users.

function get_author_posts_count( $min_posts = 1, $max_posts = 10, $limit = 10, $post_type="post" )
{
    global $wpdb;

    $authors = $wpdb->get_col(
        $wpdb->prepare(
            "SELECT post_author FROM (
                SELECT post_author, COUNT(*) AS count 
                FROM $wpdb->posts
                WHERE post_type = %s 
                AND post_status="publish" 
                GROUP BY post_author
            ) AS stats
            WHERE stats.count BETWEEN %d AND %d
            ORDER BY RAND()
            LIMIT 0,%d",
            $post_type,
            $min_posts,
            $max_posts,
            $limit
        )
    );

    return $authors;
}

As you can see, I have included 4 parameters here.

  • $min_posts -> Minimum amount of published posts an author must have. Default 1

  • $max_posts -> As you would like to get authors with low post count, I have included a maximum post count. You can remove that if you wish, just remember to change the SQL accordingly then Default 10

  • $limit -> The amount of post authors to get. Default 10

  • $post_type -> The post type to get use. Default post

You can then use the function above in your WP_User_query as follow

$args = [
    'include' => get_author_posts_count( 5, 20, 5, 'my_post_type' )
];

$authors = new WP_User_Query( $args );

EDIT

From comments (thanks @birgire), there are a few issues that you should take note of

  • Before passing the result of get_author_posts_count() to the include parameter of WP_User_Query, you should check whether or not if any values are available. If the result of get_author_posts_count() is empty or invalid, the include parameter will be ignored and all users will be returned. The query will not return an empty array of users

  • There is a limit on the lenght of an SQL query, so very big author queries might crash. As I already stated, my test site is really small, so I cannot test my code to the max. You should also check out this post on SQL query lentghs

I would appreciate any feedback on tests on large sites with many posts and plenty authors

Leave a Reply

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