Front-End Author Listing And User Search For WordPress

Advertisement

This article will guide you through the process of creating a front-end page in WordPress that lists your authors. We’ll discuss why you would want to do this, we’ll introduce the WP_User_Query class, and then we’ll put it it all together.

User Engagement And WordPress

At 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.

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

user-listing

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 for author.
  • offset
    The first n 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: http://cozmoslabs.com
Description: Create a simple shortcode to list our WordPress users.
Author: Cristian Antohe
Version: 0.1
Author URI: http://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: http://cozmoslabs.com
Description: Create a simple shortcode to list our WordPress users.
Author: Cristian Antohe
Version: 0.1
Author URI: http://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 the GET parameter as if it exists.
  • $page
    The get_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 what get_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!

(al)

↑ Back to top

Cristian Antohe is part of the team that built Profile Builder Pro, a front end registration, login, edit profile and user listing plugin for WordPress. He’s a WordPress developer, web designer and Open Source fanatic. A couple of years ago he co-founded Reflection Media, a "custom WordPress solutions" company and every Thursday curates wpMail.me, the free weekly WordPress newsletter.

  1. 1

    Adrian Pirvulescu

    June 5, 2012 10:59 am

    Well done Cristi !

    Looking forward to your next article, meanwhile keep up the great work!
    Cheers!

    3
  2. 2

    Looks awesome, but I can’t get it to work. Copied the full code into new plugin, activated. Used defaults with [userlisting] shortcode. Search field is displayed: http://fortheipad.com/authors/ – but no users. I have about 7 contributors and an admin user that should be shown. Do you have a working example somewhere?

    3
    • 3

      In the script it reads:

      // Generate the query
      $my_users = new WP_User_Query(
      array(
      ‘role’ => ‘author’,
      ‘offset’ => $offset ,
      ‘number’ => $number
      ));

      Remove author from role or set to the role you wish to output.

      // Generate the query
      $my_users = new WP_User_Query(
      array(
      ‘role’ => ”,
      ‘offset’ => $offset ,
      ‘number’ => $number
      ));

      If you have no authors, you get no output.

      2
      • 4

        Thanks Matt, that did the trick! By the way, you really ought to turn on notifications when a comment has been replied to, I had no idea you’d responded yet. “Reply-Me” wordpress plugin works great, and really helps with retaining users I’ve found.

        0
  3. 5

    Great work dude.
    But, does it list authors with zero posts ?

    0
  4. 7

    Good stuff! I’ve got several sites I could use this on where I’m currently using BuddyPress. BP has certain gone in the wrong direction a number of times. They had a confusing group only forum implementation, which has gotten better in the past few months and an awful templating system, which they’re currently working on by adopting bbPress’ method. BP components can be deactivated though. You could, for example, disable all components except X-profile. Then all that BP is, is a user profile extender, which would be great for author pages.

    Example: http://ccph.carleton.ca/members/james/

    0
  5. 8

    Readers may also be interested in this wordpress plugin for multi-author blogs. It shows a pop up bar next to authors’ names with links to their social media profiles
    http://wordpress.org/extend/plugins/prosocial/

    0
  6. 9

    It was giving some error at the first time, but worked on Localhost as I forgot to add <?php in the beginning of the file, silly mistake. Well, this is what I was looking for. I wanted to make without a plugin so, integrated in my theme.

    1
  7. 10

    Thank you for making this post. It came right when I was looking for an easy way to do this in wordpress instead of setting up a new website and figure out how to do basic SQL by myself. I was hoping to create a site that would display users with different data and search functions. I could use this and add in more functionalities to it.

    Just a quick question, when using the search function, will the results not be paginated?

    0
  8. 11

    Esteban Mucientes (@mediotic)

    June 11, 2012 11:38 am

    Hey there!!

    1st, great job Christian. It’s just what we need for a blog with almost 50 authors.

    As I’m not a code-savvy, I’d like to know how to list the authors using several compositions, such as ordered by posts or by it’s sign-up date. Has anyone of you tried it out?

    0
  9. 13

    Nispaara Solutions

    June 13, 2012 9:45 pm

    Thank you for sharing!!!!!!!!!!!!!!!! Very informative.

    0
  10. 14

    Hello, please I can’t get the code to work on my localhost. I copied the code into a new file named simple-user-listing.php, put into a folder and then copied into the plugins folder. On activation, I got the error: “plugin could not be activated because it triggered a fatal error”. Parse error: syntax error, unexpected $end in directorysimple-user-listing.php on line 129.

    Please what could be the cause of this? Can you please provide a working plugin one can just download and test? Would be greatly appreciated. Thanks.

    2
    • 15

      I have a similar error on localhost as well: “Parse error: syntax error, unexpected end of file in Directorysimple-user-listing.php on line 134″.

      Line 134 for me is simply the closing ?>

      Which is right after:

      // Add the shortcode to WordPress.
      add_shortcode(‘userlisting’, ‘sul_user_listing’);

      Anyone have any idea on this? I copied the entire code from the post, no modification whatsoever.

      3
      • 16

        I had the same problem as Chris. The culprit was line 105. Solved it by adding php after the first question mark (cant paste the code as gets hidden)

        0
  11. 17

    I am having problem in the display of authors when listed. I tried to search a specific author but it displays the author’s info ten times in the list area.

    0
  12. 18

    I enjoyed your post about using wp_user_query. I’m trying to do something similar, but keep hitting a wall. The goal is to create a drop-down menu governed by $values, where ‘options’ is the text that displays in the drop-down, and ‘value’ is the actual value assigned to the variable. After I do a query filtering for just role=author, I want the options (display) to be the login name (i.e. John Smith) and I want the value passed to the variable to be the User ID # (i.e. 6). Here’s the relevant part of the code I’m using — but while the options part works, the value part doesn’t.

    $wp_user_search = new WP_User_Query( array( ‘role’ => ‘author’, ‘fields’ => array(‘user_login’, ‘ID’) ) );
    $authors = $wp_user_search->get_results();
    $values['options'] = array();
    $values['value'] = array();

    foreach ($authors as $a)
    {
    $values['options'][$a->ID] = $a->user_login;
    $values['value'] = $a->ID;
    }

    Any suggestions would be greatly appreciated!

    Cheers,
    Mark

    0
  13. 19

    Véronique Trudel

    August 28, 2012 12:33 pm

    Do you know how to change the search form term. It seems to be searching by login name only. What if we need it to search by last and first names?

    Thank you and great plugin!

    2
  14. 20

    Thanks for the plug.
    Began to integrate their One website.
    There are problems:
    1. Navigation does not work (not properly formed link next pages, and if the url to page manually, the search results are the same on all pages).
    2. Search is only a login and does not look for the name.
    3. How to sort by value get_userdata

    1
  15. 21

    Hi GREAT plugin been looking for this for ages could never code it myself! .. Just wondered if it is possible to list all authors by default so if some loads the default page and does not enter a search name it just list all authors in the database?

    Thanks

    0
  16. 22

    Aw, this was a really good post. Taking a
    few minutes and actual effort to produce a very good article… but what can I say… I put things off a lot and don’t manage to get nearly anything done.

    Prescription Safety Glasses

    0
  17. 23

    Nice article, with a few tweaks – as above, I can’t work out how to search for ‘first name’ ‘last name’ only ‘login’

    Also – ws256 – I found the navigation needed tweaking:

    From:
    href=”page/<?php

    To:
    href="/page/<?php

    Difference = /page/

    0
  18. 24

    Great article covering how to get things done. One thing I always wish were present in articles like this is a sense of what is being cached to the object cache and when. In my case I need to be very concerned about performance, and functions like this can cause a lot of queries if you’re not careful. Does WP_User_Query cache usermeta the way WP_Query caches postmeta? Does using get_userdata pull from the cache the way get_post() does?

    0
  19. 25

    Tanbin Islam Siyam

    April 4, 2013 3:35 am

    It should be-
    $total_pages = intval(ceil($total_authors / $number));
    instead of,
    $total_pages = intval($total_authors / $number) + 1;

    Because if $totat_authors==$number, 1+1=2, so it will take two pages instead of one. In some other cases like, if $totat_authors=6 and $number=3, it will show one extra page.

    Better take the ceil and problem solved.

    0
  20. 26

    For anyone interested, I packaged up this tutorial as a plugin for the official repo:

    http://wordpress.org/extend/plugins/simple-user-listing/

    I moved all the HTML sections to template parts that you can override in your theme and also added support for custom order by parameters.

    1
  21. 27

    Love this little plugin. I am using it in conjunction with cimy user extra fields for a client with an extended member database using custom roles.

    Only one little issue I’m trying figure out how to solve: multiple word queries. A single word query, such as the member first name, works like a charm.

    Multiple word queries, such as FirstName LastName, return nothing. I assume it has something to do with the sanitize_text_field for the search variable. I’m just good enough at PHP and WordPress to be dangerous; any help would be greatly appreciated.

    0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top