• Skip to primary navigation
  • Skip to main content
  • Skip to footer
  • Books
    • Content Strategy for WordPress (2015)
    • WordPress for Web Developers (2013)
    • Beginning WordPress 3 (2010)
  • Blog
    • Content Modeling for WordPress
    • WordPress Hidden Gems
    • Web Design
  • Work
    • MLIS Class Projects (2019-2022)
    • Portfolio (2002-2019)
    • Services
    • WordPress Plugins
    • WordPress Themes
    • Presentations and Interviews
    • on GitHub →

Stephanie Leary

Writer, WordPress consultant, recent MLIS grad

  • About
    • Press Kit
    • Presentations and Interviews
  • Contact Me

Creating a user directory, part 2: Building the page template

January 30, 2010 Stephanie Leary 25 Comments

In the first installment, we added some contact fields for our users. Now we’re going to build the page template that displays the user directory.

Make a copy of your theme’s page template (page-users.php) and give it a distinct name (“User Directory Template”). Replace its loop with this:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="post" id="post-<?php the_ID(); ?>">

<h2 class="pagetitle"><?php the_title(); ?></h2>
<?php
        $blogusers = get_users_of_blog(); //get all registered users
	    foreach ($blogusers as $bloguser) {
			$user = get_userdata($bloguser->user_id); //get data about each user as an object
				// create a flat array with only the fields we need
				$allusers[$user->ID] = array(
					'last' => $user->last_name,
					'first' => $user->first_name,
					'nicename' => $user->user_nicename,
					'title' => $user->title,
					'phone' => $user->phone,
					'email' => $user->user_email
				);
		}
		asort($allusers);   // sort the users by last name
		?>
<table id="staff-directory" class="sortable">
<thead>
<tr>
<th>Name</th>
<th>Title</th>
<th>Phone</th>
<th>Email</th>
<th class="unsortable">Add</th>
</tr>
</thead>
<tbody>
		<?php
		foreach ($allusers as $auser) {  ?>
<tr class="vcard" id="<?php echo $auser['nicename']; ?>">
<td class="fn uid"><?php echo $auser['last'].", ".$auser['first']; ?></td>
<td class="title"><?php echo $auser['title']; ?></td>
<td class="tell"><?php echo $auser['phone']; ?></td>
<td class="email"><a href="mailto:<?php echo $auser['email']; ?>"><?php echo $auser['email']; ?></td>
<td><a href="http://h2vx.com/vcf/YOUR-URL/?p=<?php echo $post->ID.'#'.$auser['nicename']; ?>">
                    <img src="/images/vcard.gif" title="Add <?php echo $auser['first'].' '.$auser['last']; ?> to your address book"
                    alt="Add <?php echo $auser['first'].' '.$auser['last']; ?> to your address book" /></a></td>
</tr>
		<?php } ?>
		</tbody>
</table></div>

    <?php comments_template(); ?>
    <?php endwhile; endif; ?>

Be sure to replace YOUR-URL with your site’s URL (without the http://) in the last table cell.

Let’s break that down a little.

First, you’ll see that we’re starting a typical loop. This lets us get the page title and comment settings. If you want some introductory content, you could add the_content(); after the title.

Here, instead of using the page’s content, we’re grabbing a list of users and looping through them to create a table. We use the get_users_of_blog() and get_userdata() WordPress functions to build an array of users. (I’ve included the user ID as the array key, but it’s not really needed unless you’re debugging something.) Once we have our array, we can use a simple asort() function to sort by last name, since that’s the first element in our array.

From here, everything should be straightforward — except, perhaps, those classes on the table rows and cells. If you haven’t worked with microformats before, this might look a little strange. The extra classes make up the hCard specification. With a little help from the H2VX service, each of those table rows can be turned into downloadable vCards that you can add to almost any address book application — and that’s exactly what the links in the last column do.

The sortable class on the table allows us to use the sortable, striped table script we wrote about a few days ago. You’ll notice that I added an unsortable class to the last column, since it wouldn’t make sense to sort the vCard links.

Here’s what the table looks like:

The completed directory

You’re not quite finished! You have to create a page in WordPress that uses this template. Add a new page. If you decided to use the_content(), go ahead an fill it in; otherwise, leave the content blank. In the Page Attributes area, choose the page you just created from the dropdown menu. Publish your post and view it. The table should appear.

And there you have it! With two loops and a little strange-looking HTML, we’ve created a complete directory of our site’s users, and even provided visitors with a way to add us to their address books.

WordPress javascript, microformats, tables, Templates, Users and Roles

Reader Interactions

Comments

  1. Piet says

    February 24, 2010 at 5:37 pm

    Hi Stephanie, many thanks for the above code example! I finally came across your post and you made my day!!!

    I have adapted the code a bit to suit my needs, but one thing I cannot figure out: I would like to be able to hide a specific person from the list. How can I do that? with an exclude user-ID command or by explicitly using the name of the person? And how and what should I do to hide that person?

    Many thanks in advance!

    Piet

    Reply
  2. Stephanie says

    February 24, 2010 at 7:01 pm

    Piet, sure! In fact, I have a bit in my working code to exclude people who haven’t entered a last name, but I took it out for the demo.

    You just need to add an if statement inside the foreach loop that generates the table rows. Here’s how mine looks:

    foreach ($allusers as $auser) { 
    			if (!empty($auser['last'])) { ?&gt;
    			&lt;tr class=&quot;vcard&quot; id=&quot;&lt;?php echo $auser['nicename']; ?&gt;&quot;&gt;
                    &lt;td class=&quot;fn uid&quot;&gt;&lt;?php echo $auser['last'].&quot;, &quot;.$auser['first']; ?&gt;&lt;/td&gt;
                    &lt;td class=&quot;title&quot;&gt;&lt;?php echo $auser['title']; ?&gt;&lt;/td&gt;
                    &lt;td class=&quot;tell&quot;&gt;&lt;span class=&quot;areacode&quot;&gt;(979) &lt;/span&gt;&lt;?php echo $auser['phone']; ?&gt;&lt;/td&gt;
                    &lt;td class=&quot;email&quot;&gt;&lt;a href=&quot;mailto:&lt;?php echo $auser['email']; ?&gt;&quot;&gt;&lt;?php echo $auser['email']; ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;a href=&quot;http://feeds.technorati.com/contacts/uwc.tamu.edu/?p=&lt;?php echo $post-&gt;ID.'#'.$auser['nicename']; ?&gt;&quot;&gt;
                        &lt;img src=&quot;/images/vcard.gif&quot; title=&quot;Add &lt;?php echo $auser['first'].' '.$auser['last']; ?&gt; to your address book&quot; 
                        alt=&quot;Add &lt;?php echo $auser['first'].' '.$auser['last']; ?&gt; to your address book&quot; /&gt;&lt;/a&gt;&lt;/td&gt;
    			&lt;/tr&gt;
    		&lt;?php } } ?&gt;
    

    To exclude a particular user ID, I would use something like this:

    foreach ($allusers as $auser) { 
                    $id = array_keys($auser);
                    // since $auser has just one element, we can safely say:
                    if ($id[0] != $user_to_exclude) {
                       // &lt;tr&gt; loop here
                    }
    		&lt;?php } } ?&gt;
    

    I haven’t tested that, but I think it should work.

    Did that make sense?

    Reply
  3. Piet says

    February 24, 2010 at 7:41 pm

    Hi Stephanie, yeah with an if statement it indeed does make sense. I was not sure however where to include it.

    So I have added it now and tested it, but it still shows everyone.

    I have tried a couple of different alterations, such as [‘1’], other user ID’s, etc., but none have the desired result.

    Do you have any other suggestions or would it help if I send you my code?

    Reply
    • Piet says

      February 24, 2010 at 8:10 pm

      OK for now I “solved” it with what you said earlier “a bit in my working code to exclude people who havenâ

      Reply
      • Stephanie says

        February 24, 2010 at 8:34 pm

        Sure. Replace this:

        if (!empty($auser['last']))
        

        with this:

        if ($auser['nicename'] != 'admin')
        
        Reply
        • Piet says

          February 24, 2010 at 10:55 pm

          Yup, that indeed does the trick!

          Thanks so much for your help Stephanie!

          I have bookmarked your post and will surely visit again :)

          Reply
  4. Piet says

    November 24, 2010 at 10:14 pm

    Hi Stephanie,
    It’s me again :) I am now trying something different altogether, but it is also based on your code.
    What I am trying to do is to hide certain menus in the WordPress Dashboard from other administrators than the first (user_id=1)
    I know this is also possible with a plugin like Members, but I don’t have that option (too complex to explain)

    So I have come up with this custom function, but it also disables the menus for the first admin (user_id=1) and that is the only id for which things should still be visible.

    I am obviously missing sth here, could you perhaps help me on my way?

    Code is here:

    // disable dashboard menus for users other than webmaster
    add_action('admin_head', 'my_custom_dash');

    function my_custom_dash() {
    $blogusers = get_users_of_blog(); //get all registered users
    foreach ($blogusers as $bloguser) {
    $user = get_userdata($bloguser->user_id); //get data about each user as an object
    // create a flat array with only the fields we need
    $allusers[$user->ID] = array(
    'userid' => $user->user_id,
    'nicename' => $user->user_nicename,
    );
    }
    asort($allusers); // sort the users by userid

    foreach ($allusers as $auser) {
    $id = array_keys($auser);
    // since $auser has just one element, we can safely say:
    if ($id[1] != $user_to_exclude) {
    echo '
    li#menu-appearance, li#menu-plugins, li#menu-settings, li#toplevel_page_page-flip-image-gallery, li#toplevel_page_w3tc_general {display:none !important;}
    ';
    }
    }
    }

    Reply
  5. Piet says

    November 24, 2010 at 10:23 pm

    Hmmm I don’t know what I was thinking, but I made this one way too complex than it should have been.

    For anyone who is interested:

    function my_custom_dash() {
    $user_id = get_current_user_id();
    if ($user_id == 1) {
    // show entire dashboard
    } else {
    echo '
    li#menu-appearance, li#menu-plugins, li#menu-settings, etc. {display:none !important;}
    ';
    }
    }

    Reply
  6. Aaron says

    December 8, 2010 at 8:04 am

    Hello,

    Do you have ideas on how I can ad a search function to search name title or phone, and just disply users that match the criteria that was put in the search box. I have tried just using the default search box and search everything, but they are not searching my users.

    Thank you for your help,

    Aaron

    Reply
  7. Aaron says

    December 15, 2010 at 7:02 pm

    Hello,

    I was wondering, when you look at the list is there a way to have the name be a hyperlink? When you click on the hyperlink, allow it to go to the author.php page for that user?

    Thanks,

    Aaron

    Reply
    • Aaron says

      December 27, 2010 at 12:24 pm

      Hello Stephanie,

      I added this code to my directory page page, but I can’t seem to get it to sort.

      do I need to add something like in regular php not in wordpress, where I have a sort query. Like this:

      First Name
      Last Name
      Title
      Department
      Phone
      ‘;

      which are all tied to queries.

      Thanks,

      Aaron

      Reply
    • Aaron says

      December 27, 2010 at 3:01 pm

      Hello Stephanie,

      I tried follo9wing the directions that you gave Fahad. It worked for me, but the wp search box no longer finds users. Is there a way that I can have the search widget search within the page template?

      Thank you,

      Aaron

      Reply
  8. Fahad says

    December 22, 2010 at 12:58 pm

    Hi,

    I have been searching for member list for a while and i think your code will best suit my needs. I did alter my function.php file in the template folder, but i did not understand the next step.
    Make a copy of your theme’s page template (page-users.php) and give it a distinct name (“User Directory Template”).

    I am sorry if this is a silly question as i am new to wordpress.

    Reply
    • Stephanie says

      December 22, 2010 at 3:17 pm

      Your theme should come with a page template (page.php). Copy this to a new file and call it page-users.php. If there is a comment block at the top of the file, which probably says something like “Page Template,” change it to “User Directory Template.” If there isn’t one (the file just starts with <?php get_header(); ?>), add it:

      <?php
      /*
      Template Name: User Directory
      */
      ?>

      Then you’ll need to go into the Dashboard and create a page to hold the member directory. On that page’s Edit screen, in the Page Attribtes section, choose the User Directory Template from the dropdown list.

      Reply
  9. Fask says

    March 15, 2011 at 4:13 am

    thanks for the tutorial. I would like 10/20 users per page, but I can not pagination to custom page? On my site all users can write articles and list of contributors is long. You have a solution?

    Reply
  10. Joe Van Steen says

    August 2, 2011 at 8:13 pm

    Stephanie,
    Are you missing a ‘>’ to go with the lone ‘?’ to close off your php statement on line 40?

    My eyes aren’t that good, but my editor and the PHP interpreter both caught it.

    Your book is great. I’m using it to come up on WP workings in rapid fashion.

    Love your stuff – and your web site – and your posts.

    You seem to have a great attitude. Your going to have a great time with the baby. I assume it’s your first. Enjoy the process. They grow up way too quickly.

    Joe

    Reply
  11. Joe Van Steen says

    August 2, 2011 at 8:21 pm

    On second look and execution, it looks like maybe its the blank and slash that are extra. The “? />” should maybe be “?>”

    Sorry about the double post. I should have fully checked it before I posted the first one.

    Joe

    Reply
    • Stephanie says

      August 2, 2011 at 8:26 pm

      Yes, the img tag continues on to the next line with the alt, so line 40 should be:

      &lt;img src=&quot;/images/vcard.gif&quot; title=&quot;Add &lt;?php echo $auser['first'].' '.$auser['last']; ?&gt; to your address book&quot;
      

      Thanks for pointing that out! I’m updating the post.

      Reply
  12. Joe Van Steen says

    August 3, 2011 at 10:46 am

    Stephanie,

    You talk here about using the sortable, striped table script for the directory. The way that code is written, it is a filter on the post. If used as your prior example shows it will not work for this because it doesn’t get triggered. The “class=’sortable'” text (which I assume you are looking for) is NOT part of the post, but part of the HTML output you are generating. I don’t know how many other people may have missed that point. I resolved it myself by doing a direct trigger of the javascript injection to get the sortable feature to work. Hopefully this may clarify that issue for others.

    Another point that I’m finding is that I believe the get_users_of_blog() function has been deprecated. I don’t know what it’s status was at the time you wrote this, but current readers would want to use another function.

    BTW – Did you publish Part 3 of this series? I couldn’t seem to find it on your site.

    Thanks again for your examples and the book. They are really helpful in learning how to work with the system.

    Reply
    • Stephanie says

      August 8, 2011 at 9:48 am

      Yes, these tutorials were written separately, and in this case you’d want to enqueue the table script in the page template.

      This was written a while back. The updated way to get users is:

      $blogusers = get_users( array( 'blog_id' =&gt; $blog_id, 'fields' =&gt; 'ids' ) ); 
      
      Reply
  13. playground089 says

    August 7, 2012 at 7:03 pm

    Thank you in advance to the help!

    Reply
  14. Abby says

    November 18, 2012 at 3:10 pm

    Hi, making use of the built-in leriabris within WordPress (mainly Transients and HTTP API) would make this code much simpler and more portable.Here’s a quick one shot of how it could work: https://gist.github.com/900356

    Reply
  15. jkd says

    August 7, 2013 at 5:17 am

    First off, thank you for this valuable resources. This is really useful.

    I just have minor issue to implement the code. Instead of get_users_of_blog() function , I am trying to use
    $blogusers = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ids' ) );

    But that will show an error like this “Notice: Trying to get property of non-object “.

    I would appreciate your suggestions. Thanks.

    Reply
  16. jkd says

    August 7, 2013 at 5:43 am

    Also how could I show the avatars for the authors.

    Reply
  17. Steven Delong says

    September 4, 2013 at 11:25 pm

    Thank you Stephanie for this post. I am fairly new with coding and this helped me get past my hurdle! It makes is so much easier to get the user meta data then the other methods I read and tried.

    Reply

Leave a Reply Cancel reply

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

Footer

My Books

I’m a front end developer at Equinox OLI, working on open source library software. I was previously a freelance WordPress developer in higher education. You can get in touch here or on LinkedIn.

Copyright © 2023 Stephanie Leary · Contact