Utilizing User Roles In WordPress

About The Author

Hello, I’m Daniel and I make things for the web. I’m the CTO at Kinsta and I write for a number of amazing publications like Smashing Magazine and … More about Daniel ↬

Email Newsletter

Weekly tips on front-end & UX.
Trusted by 200,000+ folks.

User roles and capabilities are extremely powerful tools in WordPress. In this article, you’ll learn everything you need to utilize user roles in WordPress and make the most of this incredible built-in functionality.

Roles have been an integral part of WordPress for quite some time now — many functions associated with managing them have been in place since version 2.0.0. Despite this longevity, they are rarely utilized which is a shame since they allow for the easy setup of custom user types (and also have the ability to micro-manage them). In this article, you’ll learn everything you need to utilize user roles in WordPress and make the most of this incredible built-in functionality.

Large view.

Terminology

The main terms to know are “role” and “capability”. Capabilities are the core of the system, they represent the things you can do. An example of a capability is switch_themes. A user who has this capability is able to change the look of the website using the Appearances section in the admin. Those who do not have this capability will not be able to do so.

Roles are simply a named set of capabilities. Imagine you have capabilities like edit_post, add_user and so on. Instead of listing all 50 of them for each and every user who you’d like to be an admin, simply assign each user the “admin” role and then assign all the capabilities to that role.

The Default Setup

By default, WordPress has six roles and about 57 capabilities. Each role has a different combination of capabilities which endow the user with the appropriate rights and privileges.

For example, a contributor can edit and delete his own posts, but cannot control when these posts are published (and cannot delete those posts once they are published). This is because they have the edit_posts and delete_posts capabilities, but they do not have the publish_post and delete_published_post capabilities.

The default setup offered by WordPress is very well thought out and should not be modified, only added to. If it is changed, you could face difficult problems later on — like a contributor being able to remove posts from your website, or an admin not being able to change the theme.

When New Roles And Capabilities Are Needed

New roles usually come hand-in-hand with new capabilities. Usually, we first create a set of new capabilities, which are held by the admin (and a new role, as well). Let’s look at an example.

If you have a large website, chances are you have a marketing team. This team doesn’t need to be able to edit and publish posts, but they do need access to advertising stats, trending search topics, etc. Perhaps it would also be beneficial to allow them to manage categories and comments for SEO purposes and customer satisfaction, respectively.

Our first order of business is to look at the advertising stats and trending searches. This is not something WordPress offers by default, so let’s presume it has been built as a plugin. Let’s create a capability called view_stats. This will be given to the marketing people and of course to the admin. Other users — like editors and authors — do not need to see the stats (which, in many case, is sensitive data) so they will not receive this capability.

Our second task is to decide what other capabilities our marketing people need. Based on our assumptions above, they will need the read, manage_links, manage_categories and moderate_comments capabilities.

Lastly, we would use some coding chops to create a new role named “Marketing”, and assign the above-mentioned capabilities to it. Once that has been done, we are able to appoint the “Marketing” role to any user within the “Add User” and “Edit Profile” page.

Basic WordPress Functions

To manage roles and capabilities effectively, all you need is five very straightforward functions:

  • add_role() — Enables you to add a custom role
  • remove_role() — Enables you to remove a custom role
  • add_cap() — Enables you to add a custom capability to a role
  • remove_cap() — Enables you to remove a custom capability from a role
  • get_role() — Gets information about a role as well as associated capabilities

If you would like to view the documentation for these functions, you can take a look at the Roles and Capabilities section in the Codex.

Implementing New Roles And Capabilities

The full implementation of roles and capabilities requires more than just the five functions I mentioned. We’ll also need to use functions for checking capabilities, we’ll need features which are only available to certain roles, and so on.

Adding The Roles And Capabilities


$marketing = add_role( 'marketing', 'Marketing', array(
    'read' => true,
    'manage_links', 
    'manage_categories', 
    'moderate_comments',
    'view-stats'
));

$role = get_role( 'administrator' );
$role->add_cap( 'view-stats' );  

The function above will add our new “Marketing” role. It adds four capabilities which are already included in WordPress and a fifth one which is a custom capability. As you can see, no special coding is required to add custom caps — just include them in the array when adding the role. Once we add the new role, we make sure to add our new capability to the admin role as well.

Note that the add_role() fuction returns a WP_Role object on success or NULL if the role already exists.

Since the above code will be used in a plugin, the best way to use it is to utilize hooks, and to add the capabilities to the administrator only when we first create the role.

add_action( ‘admin_init’, ‘add_custom_role’ );

function add_custom_role() { $marketing = add_role( ‘marketing’, ‘Marketing’, array( ‘read’ => true, ‘manage_links’, ‘manage_categories’, ‘moderate_comments’, ‘view-stats’ ));

if( null !== $marketing ) { $role = get_role( ‘administrator’ ); $role->add_cap( ‘view-stats’ ); } }

Checking For Capabilities And Roles

Once we have our system in place we can check for capabilities and roles. This allows us to make sure that only users with the right capabilities can do certain things.


add_action('admin_menu', 'register_stats_Page');

function register_stats_Page() {
    add_menu_page( 'Marketing Info', 'Marketing Info', 'view_stats', 'marketing-info', 'show_marketing_info' );
}

function show_marketing_info(){
   if( ! current_user_can( 'view-stats' ) ) {
      die( 'You are not allowed to view this page' );
   }
   echo "
This is the marketing stats page
"; 
}  

The code above will add a top level menu to the admin area for our marketing stats page. The add_menu_page() function allows you to specify a capability (the third argument) which determines whether or not the menu is shown.

Note that even though the add_menu_page() function itself takes the capability as an argument, we still need to check for it in the function which displays the content of the page.

This leads us into our next two functions nicely: current_user_can() and user_can().

If you want to check whether or not the currently logged-in user has a specific capability, simply use the following format:


if( current_user_can( 'any_capability' ) ) {
    // The user has the capability
}
else {
    // The user does not have the capability
}  

If you would like to check whether or not an arbitrary user has a specific capability, use the user_can() function:


if( user_can( 45, 'any_capability' ) ) {
    // The user with the ID of 45 has the capability
}
else {
    // The user with the ID of 45 does not have the capability
}  

In addition to capabilities, both functions can check for roles as well:


if( current_user_can( 'marketing' ) ) {
    // The current user is a marketing person
}
else {
    // The current user is not a marketing person
}  

Creating User Types

While not an official term, I call different roles “user types” when they require many different front-end changes. Say you’re building a theme marketplace, for example. Apart from the administrator who oversees all (and the authors who would write in the company blog) you also have buyers and sellers. These are both registered users of your website but would require somewhat differing front-ends.

The profile page of a buyer would most likely show the number of things he’s bought, how frequently he buys stuff and when logged in, he would see a list of downloads.

A seller’s profile would be a portfolio of his work, his most popular items, and so on. When logged in he should probably see sales statistics.

Figuring Out Roles And Permissions

To make things simple, users either buy or sell, and cannot do both. Let’s create the two roles with a set of capabilities (off the top of my head…):


add_action( 'admin_init', 'add_custom_roles' );

function add_custom_roles() {
    $seller = add_role( 'seller', 'Seller', array(
        'read' => true,
        'delete_posts' => true,
        'edit_posts' => true,
        'delete_published_posts' => true,
        'publish_posts' => true,
        'upload_files' => true,
        'edit_published_posts' => true,
        'view_sales' => true,
        'moderate_comments' => true
    ));

    $role = get_role( 'administrator' );

    if( null !== $seller ) {
        $role->add_cap( 'view_sales' );
        $role->add_cap( 'view_others_sales' );
   }

    $buyer = add_role( 'buyer', 'Buyer', array(
        'read' => true,
        'add_payment' => true,
        'download_resources' => true
    ));

    if( null !== $buyer ) {
        $role->add_cap( 'add_payment' );
        $role->add_cap( 'add_others_payment' );
        $role->add_cap( 'download_resources' );
        $role->add_cap( 'download_others_resources' );
   }

}  

The idea here is that sellers are like authors, who will store sellable items as posts. Therefore, they receive the capabilities of an author. In addition, they can also view sales stats for their own items.

In addition to viewing items, buyers can also add payments and download files related to items that they buy.

Admins receive all these permissions, but in addition, they may view the statistics of any other user, add payments to any account, and may download resources for any item.

Frontend Implementation

From here on out it’s a matter of using our role and capability checking functions to determine who sees what. Let’s take a look at a couple of examples:

Listing Users

If we list all the users on the website, we could show the items bought for the buyers and the items sold for the sellers. Here’s how:


<!-- 
  User Data comes from a WordPress user object stored in the $user variable 
--> 

<div class='user'>
  <div class='row'>
    <div class='threecol'>
      <?php echo get_avatar( $user->ID, 120 ) ?>
    </div>
    <div class='sixcol'>
      <h1><?php echo $user->display_name ?></h1>
      <?php echo $user->description ?>
    </div>
    <div class='threecol last'>
      <?php if( user_can( $user->ID, 'buyer' ) ) : ?>  
        <div class='counter'>
          <span class='number'><?php get_purchases_count( $user->ID ) ?></span>
          <span class='text'>purchases</span>
        </div>
      <?php else ?>
        <div class='counter'>
          <span class='number'><?php get_sales_count( $user->ID ) ?></span>
          <span class='text'>sales</span>
        </div>      
      <?php endif ?>
    </div>
  </div>
</div>  

Most of this is plain old HTML, but the important thing to take away is how the counter is created. Note that the get_purchases_count() and get_sales_count() functions are fictitious (they are not part of WordPress, of course).

Of course, in a real world example we would need to make sure that only buyers and sellers are listed, and we might need to create a separate template for them completely (if the differences are numerous enough).


foreach( $users as $user_id ) {
    $user = get_userdata( $user_id );
    if( user_can( $user->ID, 'buyer' ) ) {
        get_template_part( 'userlist', 'buyer' );
    }
    else {
        get_template_part( 'userlist', 'seller' );
    }
}  

When looping through our users above, either userlist-buyer.php or userlist-seller.php will be used, depending on the user’s role.

Conclusion

User roles and capabilities are extremely powerful tools in WordPress. Whenever you build a plugin which requires the implementation of special user-based functions, you should consider using them.

Apart from making your life easier (and more manageable) it will make the processes on your websites easier to follow and easier to backtrack any problems.

Further Reading

Smashing Editorial (jvb, il, jc, js, mrn)