WordPress ships with five built-in roles: Administrator, Editor, Author, Contributor, and Subscriber. For client sites and membership platforms, you often need a custom role — “Event Manager”, “Store Manager”, “Premium Member” — with a precise set of capabilities.
Problem: WordPress's built-in roles do not map cleanly to custom business requirements — there is no native way to create fine-grained permission groups or restrict specific admin features to specific user types.
Solution: Use add_role() to create a custom role with a specific capability set, get_role()->add_cap() to extend an existing role, and current_user_can() throughout your code to gate features behind the correct capability.
Add a custom role on plugin activation:
register_activation_hook( __FILE__, 'create_event_manager_role' );
function create_event_manager_role() {
add_role(
'event_manager',
__( 'Event Manager', 'textdomain' ),
[
// Standard WordPress capabilities
'read' => true,
'edit_posts' => false,
'delete_posts' => false,
// Custom capabilities for a hypothetical 'event' CPT
'edit_events' => true,
'edit_published_events' => true,
'publish_events' => true,
'delete_events' => false,
'read_private_events' => true,
]
);
}
register_deactivation_hook( __FILE__, function() {
remove_role( 'event_manager' );
} );
Map the custom capabilities on the CPT registration:
register_post_type( 'event', [
'label' => __( 'Events', 'textdomain' ),
'public' => true,
'capability_type' => 'event', // generates edit_events, publish_events, etc.
'map_meta_cap' => true, // let WordPress handle per-post checks
'capabilities' => [
'edit_post' => 'edit_event',
'edit_posts' => 'edit_events',
'edit_others_posts' => 'edit_others_events',
'publish_posts' => 'publish_events',
'read_private_posts' => 'read_private_events',
'delete_post' => 'delete_event',
'delete_posts' => 'delete_events',
],
] );
Add or remove a capability from an existing role at runtime:
// Give editors the ability to manage WooCommerce
$editor = get_role( 'editor' );
$editor->add_cap( 'manage_woocommerce' );
// Remove a capability
$editor->remove_cap( 'delete_others_posts' );
NOTE: Role and capability data is stored in the wp_user_roles option in the database. Calling add_role() on every page load is harmless but wasteful — run it only on plugin activation. Similarly, use add_cap() and remove_cap() in activation/setup hooks rather than on init.