Utilizing User Roles In WordPress

Advertisement

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.

1
Large view2.

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 setup3 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 Capabilities4 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.

(jvb) (il) (jc) (js)

Footnotes

  1. 1 http://www.smashingmagazine.com/wp-content/uploads/2012/08/rolemananagement.jpg
  2. 2 http://www.smashingmagazine.com/wp-content/uploads/2012/08/rolemananagement.jpg
  3. 3 'http://codex.wordpress.org/Roles_and_Capabilities#Roles'
  4. 4 'http://codex.wordpress.org/Roles_and_Capabilities#Resources'

↑ Back to topShare on Twitter

Daniel is not only a web developer who is in love with WordPress, but also the Editor of the Smashing WordPress section. He owns a company called Bonsai Shed where they make web apps and premium themes like Musico and Estatement.

Advertising
  1. 1

    not quite what I was expecting to see. I presume to do this purely from the admin somebody would need to have created a roles/users plugin yes?

    -8
    • 2

      I’m sorry it wasn’t exactly up your alley! I see where you’re coming from though and the answer is yes, you’ll need a plugin to create and manage roles if you’re not familiar with programming. There are a few out there, I think Role Scoper is pretty good, but please read some reviews before you try it :)

      5
    • 3

      User Role Editor is a basic role/capability editor as well.

      2
  2. 4

    Nice and useful article, though you have a minor mispelling here: “both fucntions can check for roles”

    Do you know of a way to easily extend one of the current roles, IE if I want a role to be “Contributor, with these added permissions”, do I need to look through the different permissions for Contributor, or is there a way to handle it better? Or in that case, am I best off giving Contributor those permissions?

    -1
    • 5

      Hi Melindrea,

      Thanks for noticing the typo, I’ll clear it up as soon as I can!

      I recommend going through permissions individually unless you really know everything well – just in case you add a permission you don’t want to. If you want to copy capabilities from a role the first thing that comes to mind is something like this:

      If you look at the code snippet under “Figuring out roles and permissions”, replace lines 30-33 with the following:

      $contributor_role = get_role( ‘contributor’ );
      $contributor_capabilities = array_keys( $contributor_role->capabilities );
      foreach( $contributor_capabilities as $capability ) {
      $role->add_cap( $capability )
      }

      You’ll need to modify the whole example to suit your needs, but that’s most of it.

      0
      • 6

        Hi Daniel!
        Great topic! I love digging in to the particulars in WordPress, and this is an area I’d like to have a better grasp.

        I’m confused a bit by this code. You are defining $contributor_role, but then not using the object anywhere. Is there an error or am I missing something obvious?

        Should the next line be $contributor_capabilities = array_keys( $contributor_role->capabilities ) ?

        0
  3. 8

    Excellent article! I especially liked how you started with a non-technical introduction to users, roles and capabilities, and then moved on to code – very good balance.

    0
  4. 9

    I’m always impressed by the number of (useful) functions WordPress has, and even after a couple of years developing with this platform, I’m learning about it everyday.
    Very interesting read, thanks for sharing your knowledge.

    0
  5. 10

    Really nice article, very useful. Thanks for sharing the knowledge!

    0
  6. 11

    Simply Brilliant

    0
  7. 12

    You should not add roles and capabilities on the admin_init hook. That code will execute on every page load in the WordPress admin, which is something you don’t want to happen. Plus, it stomps on role management plugins when you do that. Adding roles and capabilities in plugins should almost always happen on the plugin activation hook (with a few exceptions, such as the Members plugin, which allows you to manage roles).

    You don’t need the current_user_can() check in your show_marketing_info() function since you already added the capability when adding the menu page. WordPress will handle that.

    4
  8. 14

    Great, plain language post for this topic that is not as complicated as it seems on the surface. Nice job.

    I like understanding he underpinnings of the codex but do you have a recommendation for a plugin to manage this? There are almost too many to review and in most cases do not require a premium plugin.

    0
  9. 15

    I have been using WordPress for years but have not used the different roles available until recently so this post is very helpful. I will check out Role Scoper that you mentioned as I am not so good at the tech stuff and a plug in would be great to manage roles.

    0
  10. 16

    You say to never change the default WP roles, which I agree with, but is there any issue in changing the way they’re named? For instance, if “Editor, “Contributor,” etc don’t fit the site’s business and would be better understood by clients to be “Manager,” “Delivery,” etc. WordPress is about so much more than blogging these days.

    0
    • 17

      Hi Jeff,

      That’s a tricky question. If you are absolutely sure you know what you’re doing then I think renaming it is fine. You can do so by changing stuff in the $wp_roles global variable.

      While I have done this as a test before, I have no idea what WordPress systems rely on naming or some other thing that this would change. I would be surprised if renaming would cause problems, but be extra careful!

      0
  11. 18

    Why don’t you just use the Members Plugin http://wordpress.org/extend/plugins/members/ by Justin and just save yourself a lot of hassle of hand coding it all…!

    0
    • 19

      Hi Matt,

      That is a great plugin, you are right, it solves a lot of problems for many people. However, these articles aren’t just aimed at people who need to quickly add roles and permissions to their website.

      Roles and permissions is something you must be familiar with if your a WordPress developer and utilising them through your own code is a great way to learn. In addition to those who need a specific task completed, there are programmers who need to know the stuff, so they can create awesome plugins like the Members Plugin :)

      2
  12. 20

    This is a great tip.
    I’m in the middle of WP user and dev but have always found the plugins for user management OK-ish at best. Knowing this is awesome. And I agree. The reality is, dabbling with code and learning yourself is always miles better than just settling for a plugin!

    Steve

    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