I'm trying to get a list of roles and filter them by a specific capability (custom). I've ran across this post, but I'd like to filter the roles by whether they're capable to, say, edit_post.


1 Answer 1


Untested, but should be easily extendable(or something you can take ideas from).

function roles_have_cap( $roles = false, $cap ) {
    global $wp_roles;

    if( !isset( $wp_roles ) || !isset( $cap ) )
        return false;

    if( !$roles )
        $roles = array_keys( $wp_roles->roles );

    if( !is_array( $roles ) )
        $roles = array( $roles );

    $hascap = array();
    foreach( $roles as $role ) {
        if( !isset( $wp_roles->roles[$role]['capabilities'][$cap] ) || ( 1 != $wp_roles->roles[$role]['capabilities'][$cap] ) )

        $hascap[] = $role;

    if( empty( $hascap ) )
        return false;

    return $hascap;
  • First argument takes either a singular role name(string) or an array of roles to check have a particular cap.
  • Second argument takes a singular capability to check for(string).

Example usage:

$role_can_edit_pages = roles_have_cap( 'administrator', 'edit_pages' ); 
// Result
// array( 0 => administrator )

If the function returned false you'd know the role(s) does not have the cap, ie..

if( !$role_can_edit_pages )
// Role cannot not edit pages

Else, the result is an array of roles that do have the cap(whether you passed in a single role or several).

You could trim it down and just have a return value if that's preferred, but you mentioned wanting a list of roles that have a cap, so i naturally assumed an array would be a logical choice..

Converting an array to a string is fairly easy, and you can even use your own seperator, simply call implode(), like so...(using the example variable from earlier)..

echo implode( ' | ', $role_can_edit_pages ); // | (pipe is the example seperator here)

You could also move the implode into the function to avoid having to do implodes when calling the function, and do note, implode will work correctly on a single item array to(ie. you'll get a string with no seperator).

I hope that's helpful in anycase... :)

EDIT: Function will now look at all the roles if the first arg($roles) is set to false.

  • Looks alright, I can follow the basic logic. Though, logistical problem I foresee. Your function checks only the specified roles for the requested capability (No problem to me, I can rewrite it easily from your logic). In fact, I can see two functions branching out from this function you provided here. ;)
    – Zack
    Feb 15, 2011 at 20:29
  • Added the option in for you, set first arg to false to look at all roles... :)
    – t31os
    Feb 15, 2011 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.