5

I have a certain number of main menus which need to showcased based on logged in user role. for example user with the role, A can sees few menus and user with the role B, sees another set of few menus.

5 Answers 5

4

This can be achieved using the routes to manage the permissions. Take the following example:

mymodule.routing.yml

mymodule.home:
  path: '/mymodule'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::overview'
    _title: 'My Module'
  requirements:
    _role: 'authenticated user'

mymodule.settings:
 path: '/admin/mymodule'
 defaults:
   _form: 'Drupal\mymodule\Form\MyModuleSettingsForm'
   _title: 'Settings'
 requirements:
   _permission: 'administer mymodule'

mymodule.view:
 path: '/mymodule/view'
 defaults:
   _controller: '\Drupal\mymodule\Controller\MyModuleController::view'
   _title: 'View'
 requirements:
   _role: 'authenticated user'

mymodule.edit:
 path: '/mymodule/edit'
 defaults:
   _form: 'Drupal\mymodule\Form\MyModuleEditForm'
   _title: 'Edit'
 requirements:
   _permission: 'edit mymodule'

mymodule.links.menu.yml

mymodule.home:
  title: 'My Module'
  parent: main
  route_name: mymodule.home
  weight: 10

mymodule.settings:
  title: 'Settings'
  parent: mymodule.home
  route_name: mymodule.settings
  weight: 10

mymodule.view:
  title: 'View'
  parent: mymodule.home
  route_name: mymodule.view
  weight: 10

mymodule.edit:
  title: 'Edit'
  parent: mymodule.home
  route_name: mymodule.edit
  weight: 10

With this approach you can display the same menu to all users, but because the links take the permissions from the routes, only users with the administer mymodule permission will be able to see the Settings link for example. You can use roles to manage it as well by using _role: '$rid'.

1
  • You can also combine roles with , and +. One means or and the other and. I don't recall which is which.
    – Gogowitsch
    May 15, 2019 at 13:16
4

In Drupal 8, you can also use the following code in your funky.module file for a programmatic approach. The approach below allows to have access rules independent of menu visibility:

/**
 * Implements hook_preprocess_menu().
 *
 * @param array[] $variables
 */
function funky_preprocess_menu(&$variables) {
  if (in_array('role_b', Drupal::currentUser()->getRoles())) {
    // Hide the menu item
    unset($variables['items']['the_key_you_used_in_your_menu_links_yml_file']);
  }
}

This assumes your module is called funky. It also assumes you have a funky.links.menu.yml file containing something similar to this:

the_key_you_used_in_your_menu_links_yml_file:
  title: 'Your menu caption'
  route_name: your_route
  menu_name: account
  cache_contexts:
    - user.roles

If you only distinguish if a user has a role or not, then you can further tighten the cache_context by that role. For the example above, user.roles:role_b would be appropriate. The documentation for cache contexts is here: https://www.drupal.org/docs/8/api/cache-api/cache-contexts

2
  • Thanks. I was creating a link to an existing route (defined by a core module) for users with a certain role, I didn't want that link to be visible for Administrators or other roles. This worked perfectly.
    – RominRonin
    Apr 14, 2021 at 11:02
  • I had to configure menus based on groups on our LDAP server, so this was the solution for me. Jul 28 at 7:19
2

Note: A solution using route permissions is the best and appropriate solution to avoid repetition and prevent a user to access/view the page using a direct link.


All you gotta do is configure your menu block

enter image description here

Then under Visibility > Roles, check mark ☑ the roles that you want to be able to view this block menu.

enter image description here

6
  • @Nossweat to add on more, It needs to be achieved for each menu item in the main menu. Something similar to menu_per_role in D7.
    – Sidhees
    Mar 1, 2017 at 10:22
  • @Sidhees Well, that module isn't going to port itself. I don't think there is anything similar out there for D8, so better start rolling-up the sleeves. Your need is quite a specific and picky need if you ask me.
    – No Sssweat
    Mar 1, 2017 at 10:47
  • 1
    This will still not solve the problem if one wants to make the link to "/user" depending on the role, either show the menu item or not, and label the menu item "role 1 thing" and another role "role 2 thing"
    – Raf A.
    Oct 1, 2018 at 5:57
  • 1
    this answer acts on the whole menu, while question is about a single menu item of a menu
    – Augusto
    Aug 12, 2021 at 21:36
  • 1
    @augusto agreed, at the time I wrote this answer, I wasn't as savvy with D8 and its code. A solution using route permissions is the better option to avoid repetition.
    – No Sssweat
    Aug 13, 2021 at 7:31
0

Just use Menu Item Role Access. It makes it much easier than writing code.

2
  • That module has a years old unresolved issue saying that uninstalling it results in sql errors site wide so I would proceed with caution.
    – ummdorian
    Jan 28 at 3:28
  • That is true about Drupal in general. I will never build a drupal site again. Jan 29 at 5:32
0

For a non-coding approach, the contrib module Menu Per Role may be of use.

This module allows you to restrict access to menu items based on user roles. Just activate the module and edit a menu item as usual. There will be a new fieldset that allows you to restrict access by role.

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.