Front-End Author Listing And User Search For WordPress
WP_User_Query
class, and then we’ll put it it all togetherAt its core, WordPress is a rock-solid publishing platform. With a beautiful and easy to use interface, and support for custom post types and post formats, publishers have the flexibility to do what they do best: write content.
Further Reading on SmashingMag:
- Modifying Admin Post Lists In WordPress
- Useful Free Admin Plugins For WordPress
- Ten Things Every WordPress Plugin Developer Should Know
- Inside The WordPress Toolbar
However, WordPress is lacking in social interaction between content authors and readers. BuddyPress is trying to solve this, but I believe it’s going in the wrong direction by trying to be a full-fledged social network.
A big phrase in the publishing world is “user engagement.” This is about getting readers to spend more time on the website, actively searching for content and even generating their own. While one could write a few books on the subject, here are a few things a WordPress publisher can do:
- Create a daily or weekly newsletter, with top stories from selected categories;
- Provide an editorial-driven open forum in which editors propose themes, stories and questions and readers comment on them;
- Continue the discussion of articles on social platforms;
- Encourage users to submit articles and images for contests;
- Highlight your authors.
Listing Authors, And Why It’s A Good Thing
If you’re a publisher, your authors are your biggest asset. They are the content creators. Their writing gets consumed by millions of people all over the world.
Showcasing them exposes them for what they really are: authorities. Your authors will thank you for acknowledging them, and readers will get to see the human face behind the technology.
Coding The Perfect Author Listing
Here are the things we want to achieve with our page:
- Build it as a WordPress plugin so that we can reuse it more easily;
- Display the name, biography, number of posts and latest published post of all authors;
- Paginate the listing if we have many authors;
- Make the listing searchable.
Introducing WP_User_Query And get_users
The WP_User_Query
class allows us to query the user database.
Besides returning an array of users, WP_User_Query
returns general information about the query and, most importantly, the total number of users (for pagination).
One can use WP_User_Query
by passing a series of arguments and listing the output.
$my_authors = new WP_User_Query(
array(
'blog_id' => $GLOBALS['blog_id'],
'role' => ’,
'meta_key' => ’,
'meta_value' => ’,
'meta_compare' => ’,
'include' => array(),
'exclude' => array(),
'search' => ’,
'orderby' => 'login',
'order' => 'ASC',
'offset' => ’,
'number' => ’,
'count_total' => true,
'fields' => 'all',
'who' => ’
));
We’ll focus on only a few arguments, rather than go through all of them:
role
This is the user’s role. In our example, we’ll query forauthor
.offset
The firstn
users to be skipped in the returned array.number
Limit the total number of users returned.
We also have the get_users
class, which (like WP_User_Query
) returns a number of users based on the parameters set.
The important difference between the two is that get_users
only returns an array of users and their meta data, whereas WP_User_Query
returns extra information such as the total number of users (which is useful when it comes time to paginate).
Simple User Listing Using get_users()
Before moving on with the full user listing, including pagination and search, let’s see get_users
in action.
If all you need is a simple list of authors, then you could just use wp_list_authors
, like so:
wp_list_authors('show_fullname=1&optioncount=1&orderby=post_count&order=DESC&number=3');
Creating A Plugin And Shortcode With A Bit More Functionality
A simple and straightforward way to build our user listing would be to create a shortcode that we could include on any page we like. Housing this type of functionality in a plugin is ideal, so that we don’t have to worry about migrating it when we change the theme.
Let’s keep it simple. Our entire plugin will consist of just one file: simple-user-listing.php
.
<?php
/*
Plugin Name: Simple User Listing
Plugin URI: https://cozmoslabs.com
description: >-
Create a simple shortcode to list our WordPress users.
Author: Cristian Antohe
Version: 0.1
Author URI: https://cozmoslabs.com
*/
function sul_user_listing($atts, $content = null) {
global $post;
extract(shortcode_atts(array(
"role" => ’,
"number" => '10'
), $atts));
$role = sanitize_text_field($role);
$number = sanitize_text_field($number);
// We're outputting a lot of HTML, and the easiest way
// to do it is with output buffering from PHP.
ob_start();
// Get the Search Term
$search = ( isset($_GET["as"]) ) ? sanitize_text_field($_GET["as"]) : false ;
// Get Query Var for pagination. This already exists in WordPress
$page = (get_query_var('paged')) ? get_query_var('paged') : 1;
// Calculate the offset (i.e. how many users we should skip)
$offset = ($page - 1) * $number;
if ($search){
// Generate the query based on search field
$my_users = new WP_User_Query(
array(
'role' => $role,
'search' => '*' . $search . '*'
));
} else {
// Generate the query
$my_users = new WP_User_Query(
array(
'role' => 'author',
'offset' => $offset ,
'number' => $number
));
}
// Get the total number of authors. Based on this, offset and number
// per page, we'll generate our pagination.
$total_authors = $my_users->total_users;
// Calculate the total number of pages for the pagination
$total_pages = intval($total_authors / $number) + 1;
// The authors object.
$authors = $my_users->get_results();
?>
<div class="author-search">
<h2>Search authors by name</h2>
<form method="get" id="sul-searchform" action="<?php the_permalink() ?>">
<label for="as" class="assistive-text">Search</label>
<input type="text" class="field" name="as" id="sul-s" placeholder="Search Authors" />
<input type="submit" class="submit" name="submit" id="sul-searchsubmit" value="Search Authors" />
</form>
<?php
if($search){ ?>
<h2 >Search Results for: <em><?php echo $search; ?></em></h2>
<a href="<?php the_permalink(); ?>">Back To Author Listing</a>
<?php } ?>
</div><!-- .author-search -->
<?php if (!empty($authors)) { ?>
<ul class="author-list">
<?php
// loop through each author foreach($authors as $author){
$author_info = get_userdata($author->ID);
?>
<li>
<?php echo get_avatar( $author->ID, 90 ); ?>
<h2><a href="<?php echo get_author_posts_url($author->ID); ?>"><?php echo $author_info->display_name; ?></a> - <?php echo count_user_posts( $author->ID ); ?> posts</h2>
<p><?php echo $author_info->description; ?></p>
<?php $latest_post = new WP_Query( "author=$author->ID&post_count=1" );
if (!empty($latest_post->post)){ ?>
<p><strong>Latest Article:</strong>
<a href="<?php echo get_permalink($latest_post->post->ID) ?>">
<?php echo get_the_title($latest_post->post->ID) ;?>
</a></p>
<?php } //endif ?>
<p><a href="<?php echo get_author_posts_url($author->ID); ?> ">Read <?php echo $author_info->display_name; ?> posts</a></p>
</li>
<?php
}
?>
</ul> <!-- .author-list -->
<?php } else { ?>
<h2>No authors found</h2>
<? } //endif ?>
<nav id="nav-single" style="clear:both; float:none; margin-top:20px;">
<h3 class="assistive-text">Post navigation</h3>
<?php if ($page != 1) { ?>
<span class="nav-previous"><a rel="prev" href="<?php the_permalink() ?>page/<?php echo $page - 1; ?>/"><span class="meta-nav">←</span> Previous</a></span>
<?php } ?>
<?php if ($page < $total_pages ) { ?>
<span class="nav-next"><a rel="next" href="<?php the_permalink() ?>page/<?php echo $page + 1; ?>/">Next <span class="meta-nav">→</span></a></span>
<?php } ?>
</nav>
<?php
// Output the content.
$output = ob_get_contents();
ob_end_clean();
// Return only if we're inside a page. This won't list anything on a post or archive page.
if (is_page()) return $output;
}
// Add the shortcode to WordPress.
add_shortcode('userlisting', 'sul_user_listing');
?>
Breaking Down The Code
The top of our plugin’s main PHP file must contain the standard header of information. This header tells WordPress that our plugin exists, and it adds it to the plugin management screen so that it can be activated, loaded and run.
/*
Plugin Name: Simple User Listing
Plugin URI: https://cozmoslabs.com
description: >-
Create a simple shortcode to list our WordPress users.
Author: Cristian Antohe
Version: 0.1
Author URI: https://cozmoslabs.com
*/
Creating a Shortcode
Adding a new shortcode in WordPress is rather easy. We find the function that returns the desired output (in our case, sul_user_listing
), and then we add it using the add_shortcode
WordPress function.
function sul_user_listing($atts, $content = null) {
// return our output
}
add_shortcode('userlisting', 'sul_user_listing');
Extracting Our Shortcode Arguments
We want to be able to list users based on their roles and to control how many users are displayed on the page. We do this through shortcode arguments. We’ll add the shortcode to our theme in this way: [userlisting role=“author” number=“15”]
. This will allow us to reuse the plugin to list our subscribers as well.
To do this, we need to use shortcode arguments:
extract(shortcode_atts(array(
"role" => ’,
"number" => '10'
), $atts));
The extract
function imports variables into our function from an array. The WordPress function shortcode_atts
basically returns an array with our arguments; and we’ll set up some defaults in case none are found.
Note that the role
default is an empty string, which would list all users regardless of their role.
Shortcodes Should Never Echo Stuff Out
The return value of a shortcode handler function gets inserted into the post content’s output in place of the shortcode. You should use return
and not echo
; anything that is echoed will be outputted to the browser but will probably appear above everything else. You would also probably get “headers already sent” type of errors.
For simplicity, we’re buffering the output through ob_start()
, so we put everything into an object and return it once we’re done.
Setting Up Our Variables
Now we can start building our listing of authors. First, we need to set up a few variables:
$search
This takes theGET
parameteras
if it exists.$page
Theget_query_var
for the pagination. This already exists in WordPress.$offset
Calculate the offset (i.e. how many users to skip when paginating).$total_authors
Get the total number of authors.$total_pages
Calculate the total number of pages for the pagination.
The Query
We actually have two queries: the default listing and the search results.
if ($search){
// Generate the query based on search field
$my_users = new WP_User_Query(
array(
'role' => $role,
'search' => '*' . $search . '*'
));
} else {
// Generate the query
$my_users = new WP_User_Query(
array(
'role' => 'author',
'offset' => $offset ,
'number' => $number
));
}
WP_User_Query->total_users and WP_User_Query->get_results
WP_User_Query provides us with two useful functions, among others:
total_users
Returns the total number of authors. This, the offset and the number of users per page will generate our pagination.get_results
Returns an object with the authors alone. This is similar to whatget_users()
returns.
The Search Form
For the search, we’re using a simple form. There’s nothing complex here.
<div class="author-search">
<h2>Search authors by name</h2>
<form method="get" id="sul-searchform" action="<?php the_permalink() ?>">
<label for="as" class="assistive-text">Search</label>
<input type="text" class="field" name="as" id="s" placeholder="Search Authors" />
<input type="submit" class="submit" name="submit" id="searchsubmit" value="Search Authors" />
</form>
<?php
if($search){ ?>
<h2 >Search Results for: <em><?php echo $search; ?></em></h2>
<a href="<?php the_permalink(); ?>">Back To Author Listing</a>
<?php } ?>
</div><!-- .author-search -->
User Data and Listing the Authors
Looping through our results is fairly simple. However, getting information about users is a bit confusing in WordPress. You see, there are a lot of ways to get user data. We could get it directly from the returned query; we could use general functions such as get_userdata
, get_user_meta
, the_author_meta
and get_the_author_meta
; or we could even use dedicated functions such as the_author_link
and the_author_posts
.
We’ll just use get_userdata
plus two other functions: get_author_posts_url
and get_avatar
.
<?php if (!empty($authors)) { ?>
<ul class="author-list">
<?php
// loop through each author foreach($authors as $author){
$author_info = get_userdata($author->ID);
?>
<li>
<?php echo get_avatar( $author->ID, 90 ); ?>
<h2><a href="<?php echo get_author_posts_url($author->ID); ?>"><?php echo $author_info->display_name; ?></a> - <?php echo count_user_posts( $author->ID ); ?> posts</h2>
<p><?php echo $author_info->description; ?></p>
<?php $latest_post = new WP_Query( "author=$author->ID&post_count=1" );
if (!empty($latest_post->post)){ ?>
<p><strong>Latest Article:</strong>
<a href="<?php echo get_permalink($latest_post->post->ID) ?>">
<?php echo get_the_title($latest_post->post->ID) ;?>
</a></p>
<?php } //endif ?>
<p><a href="<?php echo get_author_posts_url($author->ID); ?> ">Read <?php echo $author_info->display_name; ?> posts</a></p>
</li>
<?php
}
?>
</ul> <!-- .author-list -->
<?php } else { ?>
<h2>No authors found</h2>
<? } //endif ?>
Pagination
We need pagination because each listing will generate two extra queries. So, if we were listing 100 people, we would end up with 200 extra queries per page. That’s a bit much, so pagination is really needed. Otherwise, for websites with many authors, the load could get so heavy that it brings down the website.
<nav id="nav-single" style="clear:both; float:none; margin-top:20px;">
<h3 class="assistive-text">Post navigation</h3>
<?php if ($page != 1) { ?>
<span class="nav-previous"><a rel="prev" href="<?php the_permalink() ?>page/<?php echo $page - 1; ?>/"><span class="meta-nav">←</span> Previous</a></span>
<?php } ?>
<?php if ($page < $total_pages ) { ?>
<span class="nav-next"><a rel="next" href="<?php the_permalink() ?>page/<?php echo $page + 1; ?>/">Next <span class="meta-nav">→</span></a></span>
<?php } ?>
</nav>
Final Thoughts
We’ve discussed the code for an authors listing, but it has so many more uses:
- List your company’s employees;
- Showcase users who have won a competition (by listing users with the role of “winners”);
- Present your company’s departments, each with its respective team (based on user roles).
If you allow users to register on your website, you could use more or less the same code to generate any listing of users based on your needs. If you require users to log in in order to comment (an effective way to stop automated spam), then listing users and their number of comments could increase engagement.
Have you used something similar for a project? If so, let us know in the comments!