I'm trying to create a role that restricts the ability to post to a specific category, hiding the other from the checkbox.

I don't want to use plugins. I'm looking for a snippet to put in functions.php. I checked all the questions/blog posts about this and no solutions worked.

I think this is the starting point..

    $result = add_role( 'category_restricted', 'Restricted to specific cat', array(
        'read' => true,
        'edit_posts' => true,
        'delete_posts' => false,

Can you help me?


2 Answers 2


You can use the get_terms hook to find all categories and restrict access to them by ID or slug, if the current user is not an admin, or in this specific case if the user doesn't have the role assigned by you.

add_filter('get_terms', 'restrict_categories');
function restrict_categories($categories) { 
    $onPostPage = (strpos($_SERVER['PHP_SELF'], 'post.php') || strpos($_SERVER['PHP_SELF'], 'post-new.php')); // check if we are in the new/edit post page
    // if (is_admin() && $onPostPage && !current_user_can('level_10')) { // check for user capabilities - level_10 is admin
    if (is_admin() && $onPostPage && themename_check_user_role( 'category_restricted' )) { // check for user role
        $size = count($categories);
        for ($i = 0; $i < $size; $i++) {            
//          if ($categories[$i]->slug != 'category_slug')
            if ($categories[$i]->term_id != '1') // then restrict the categories by ID

    return $categories;

Credits for the code goes to: wptricks. I just remembered that I read about this a while ago.

Later edit:

You can try to pass a role to the current_user_can() function but it's not guaranteed to work correctly, instead you can use the function below to check for user roles.

 * Checks if a particular user has a role. 
 * Returns true if a match was found.
 * @param string $role Role name.
 * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
 * @return bool
function themename_check_user_role( $role, $user_id = null ) {

    if ( is_numeric( $user_id ) )
    $user = get_userdata( $user_id );
        $user = wp_get_current_user();

    if ( empty( $user ) )
    return false;

    return in_array( $role, (array) $user->roles );

// example use for the current user
if ( themename_check_user_role( 'customer' )
    _e( "You've got access!", 'themename' );
    _e( "Sorry, you don't have access!", 'themename' );

And as a side note, it is a good idea to include your add_role function on theme/plugin activation.

  • Uhm, but where do I specify the restricted categories and the role? Commented Dec 28, 2014 at 0:21
  • I've updated the code with more explanations and I've replaced the check for category slug with a check for category ID. Commented Dec 28, 2014 at 0:42
  • Perfect! It works! :D One last thing, instead of current_user_can can I specify the user role name? Commented Dec 28, 2014 at 1:17
  • Yes, that's correct. I modified the code again and I've included a function which will help you check if the current user has a specific role. Commented Dec 28, 2014 at 13:04
  • this is a hack that is basically equivalent to using JS to remove the term from the meta box. If the only required effect is visual that might be enough but for anything more serious the only solution is to use capability related filters Commented Aug 18, 2018 at 18:26

Create template file called not_allowed_user.php then add below code in function.php

add_filter('template_include', 'restrict_by_category');

function check_user() {
  $user = wp_get_current_user();
  if ( ! $user->ID || in_array('subscriber', $user->roles) ) {
    // user is not logged or is a subscriber
    return false;
  return true;

function restrict_by_category( $template ) {
  if ( ! is_main_query() ) return $template; // only affect main query.
  $allow = true;
  $private_categories = array('cat_1', 'cat_2', 'cat_3'); // categories subscribers cannot see
  if ( is_single() ) {
    $cats = wp_get_object_terms( get_queried_object()->ID, 'category', array('fields' => 'slugs') ); // get the categories associated to the required post
    if ( array_intersect( $private_categories, $cats ) ) {
      // post has a reserved category, let's check user
      $allow = check_user();
  } elseif ( is_tax('category', $private_categories) ) {
    // the archive for one of private categories is required, let's check user
    $allow = check_user();
  // if allowed include the required template, otherwise include the 'not-allowed' one
  return $allow ? $template : get_template_directory() . '/not_allowed_user.php';

I know you don't want to use plugin,but incase if you want to use plugin then this is best plugin : Restrict Categories

  • Thanks for the reply. :) But this just hides posts in specific categories. I'm looking for a way to restrict the ABILITY TO POST in specific categories. Commented Dec 21, 2014 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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